HexString to Byte array: Speed Freaks! Can you code this faster in C#?

R

Russell Mangel

The following code simply creates a byte array from a HexString.
Can anyone improve the perfomance of this method?

Thanks
Russell Mangel
Las Vegas, NV

String hexString = "AABBCCDDEEFF";
Byte[] Bytes = new byte[hexString.Length / 2];

Int32 len = Bytes.Length;

Int32 numLoops = 1000000;
Int32 start = System.Environment.TickCount;

for(int k = 0; k < numLoops; k++)
{
int j = 1;
for(int i=0; i < len; i++)
{
Bytes = Byte.Parse(hexString[j-1].ToString()+
hexString[j].ToString(),System.Globalization.NumberStyles.HexNumber);
j += 2;
}
}

// My P4 3Ghz Computer, does this in 3500 ms, can you do better?
Console.WriteLine("{0} ms", System.Environment.TickCount - start);
 
C

Chris A. R.

Just optimizing your current code can bring in some better results. For
"equivalence sake", I'm assuming you want all of the processing within the
outer for loop to be the same or there could be even more optimizations. By
the way, TickCount is NOT a high performance counter, so will not give you
very good differentiation in your results.

Int32 len = hexString.Length;
....
for(int k = 0; k < numLoops; k++)
{
System.Globalization.NumberStyles ns =
System.Globalization.NumberStyles.HexNumber;
for(int i=0; i < len; i+=2)
{
Bytes[i/2] = Byte.Parse( hexString.Substring(i, 2), ns );
}
}

Chris A.R.
 
J

Jon Skeet [C# MVP]

Russell Mangel said:
The following code simply creates a byte array from a HexString.
Can anyone improve the perfomance of this method?

Yup - I've got a version that's about 50 times as fast. It also doesn't
generate any garbage. It does rely on a lookup table which needs to be
created once, but that's a one-time hit.

I also investigated using a switch/case and just quick if/else clauses,
and while both were fast, this was the fastest.

Taking out the exception generation makes it even faster, but I wanted
to leave it in for correctness.

Here's my complete test code, including your version as well.

using System;

class Test
{
const int Iterations = 10000000;

static void Main()
{
// JIT the methods first
ParseRussell();
ParseJon();

// Now test them
DateTime start = DateTime.Now;
ParseRussell();
DateTime end = DateTime.Now;
Console.WriteLine ("Russell's implementation: {0}", end-start);
start = DateTime.Now;
ParseJon();
end = DateTime.Now;
Console.WriteLine ("Jon's implementation: {0}", end-start);
}

static readonly byte[] LookupTable;

static Test()
{
LookupTable = new byte[65536];
for (int i=0; i < 65536; i++)
{
LookupTable=255;
}
for (char c = '0'; c <= '9'; c++)
{
LookupTable[c]=(byte)(c-'0');
}
for (char c = 'a'; c <= 'f'; c++)
{
LookupTable[c]=(byte)(c-('a'-10));
}
for (char c = 'A'; c <= 'F'; c++)
{
LookupTable[c]=(byte)(c-('A'-10));
}
}

static void ParseJon()
{
String hexString = "AABBCCDDEEFF";
byte[] bytes = new byte[hexString.Length / 2];

int len = bytes.Length;

for(int k = 0; k < Iterations; k++)
{
int index=0;
for (int i=0; i < len; i++)
{
byte v1 = LookupTable[hexString[index++]];
byte v2 = LookupTable[hexString[index++]];
if (v1==255 || v2==255)
{
throw new FormatException ("Invalid hex string");
}

bytes=(byte)((v1<<4) + v2);
}
}
}

static void ParseRussell()
{
String hexString = "AABBCCDDEEFF";
Byte[] Bytes = new byte[hexString.Length / 2];

Int32 len = Bytes.Length;

Int32 numLoops = Iterations;

for(int k = 0; k < numLoops; k++)
{
int j = 1;
for(int i=0; i < len; i++)
{
Bytes = Byte.Parse(hexString[j-1].ToString()+
hexString[j].ToString(),
System.Globalization.NumberStyles.HexNumber);
j += 2;
}
}
}
}
 
G

Guest

Hi Russell,

I think you may follow Russell's suggestion to do the string operation
through String.Substring method.

This change will improve the speed of string operation. I have tested it,
and it can really improve the performance greatly.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
J

Jon Skeet [C# MVP]

Jeffrey Tan said:
I think you may follow Russell's suggestion to do the string operation
through String.Substring method.

This change will improve the speed of string operation. I have tested it,
and it can really improve the performance greatly.

There's no need to use String.Substring at all - that creates a new
string for each operation, when it's perfectly acceptable to take a
character at a time, which doesn't involve creating any new objects.

See my other post for a *much* faster way of doing things. I'm sure
it's not the fastest way possible, but it's pretty good.
 
M

Marcus Andr?n

The following code simply creates a byte array from a HexString.
Can anyone improve the perfomance of this method?

I was bored and decided to do some general experimenting with this
problem. From the beginning I am assumed that the hexstring consists
only of numbers and capital letters. All algorithms expects wellformed
data and does not guarantee nice error handling. Some of the
algorithms could easily be transformed to handle more complex input
data though.

Before I continue I would also like to mention that when implementing
an optimized algorithm in production code it is recommended that you
have test cases that compares the result with a non optimized version
to make sure that no mistakes is made. Premature optimization is also
never a good idea.


Here is a list sorted by performance from worst to best (in seconds
for a number of iterations)

Original 528
Boolean 9,0
Inlined Boolean 8,9
Look-Up Table 7,9
If-Else 7,1
Inlined If-Else 6,3
Unsafe Boolean 5,4

Following is an overview of all the different algorithms:

1. Look-Up Table

This was the first program I came up with. It uses a simple
pre-calculated table to look up the value of any input character. As
expected it is pretty fast and it can also easily be extended to
support 'a'-'f' without performance loss.

Byte[] lookup = new byte[256];
byte counter = 0;
for(char c='0';c<='9';c++)
{ lookup[c] = counter;counter++;}
counter = 10;
for(char c='A';c<='F';c++)
{ lookup[c] = counter;counter++;}

for(int i=0;i<hexString.Length;i+=2)
Bytes[i>>1] = (byte)((lookup[hexString] << 4) +
lookup[hexString[i+1]]);


2. If-Else

Instead of using a look-up table the above program could easily be
modified by calling a method that calculates the correct value on the
spot. I was suprised when I noticed that this actually was faster than
looking up the value. The only disadvantage is that it suffers a large
performance hit, probably to the il not inlining, when extending to
handle 'a'-'f'

for(int i=0;i<hexString.Length;i+=2)
Bytes[i>>1] = (byte)((GetVal(hexString) << 4) +
GetVal(hexString[i+1]));

static int GetVal(char c){
if(c <= '9') return c - '0';
else return c - 'A' + 10;
}

3. Inlined If-Else

This is the same as the above program except that instead of calling a
function I calculate the value inside the for loop. This seems to
yield a slight performance increase. It is fast and versitile. It is
less readable than look-up table or ordinary if-else.

4. Boolean Logic

Avoiding jumps in the code can sometimes speed up program execution so
I decided to write a simple boolean version of GetVal. The efficency
was slightly lower than the other methods.

static int GetVal(char c){
return (c & 15) + ((c & 64) >> 3) + ((c & 64) >> 6);
}

5. Inlined Boolean Logic

Inlining boolean logic didn't seem to help. The IL compiler inline
seems to be working smothly already.

6. Unsafe Boolean Logic

In a final attempt to pull the most out of c# I decided to do an
unsafe version of boolean logic that accessed two letters at a time.
This proved to be the most efficent program, although not that
readable. Do not use unless maximum performance is needed.

fixed(char* c = hexString){
int* num = (int*) c;
for(int i=0;i<hexString.Length>>1;i++){
int t = (num & 983055) + ((num & 4194368) >> 3) + ((num &
4194368) >> 6);
t = t & 983055;
Bytes = (byte)((t << 4) | (t>>16));
}
}
 
C

Chris A. R.

I wish I had that much time on my hands! All I did was clean up the
code 'as-is' though I did think about using integer math as a faster way, as
you and Jon have done. There's an unsafe-code method I have in mind that
I'll try "if" I get time later.
However, this does point out that knowing precise methodology can help
prevent bottlenecks in code. That's what makes exercises such as these very
important for those who don't know these techniques, as well as refreshers
for those who do, but haven't had a need for such tight code recently.

Chris A.R.

Marcus Andr?n said:
The following code simply creates a byte array from a HexString.
Can anyone improve the perfomance of this method?

I was bored and decided to do some general experimenting with this
problem. From the beginning I am assumed that the hexstring consists
only of numbers and capital letters. All algorithms expects wellformed
data and does not guarantee nice error handling. Some of the
algorithms could easily be transformed to handle more complex input
data though.

Before I continue I would also like to mention that when implementing
an optimized algorithm in production code it is recommended that you
have test cases that compares the result with a non optimized version
to make sure that no mistakes is made. Premature optimization is also
never a good idea.


Here is a list sorted by performance from worst to best (in seconds
for a number of iterations)

Original 528
Boolean 9,0
Inlined Boolean 8,9
Look-Up Table 7,9
If-Else 7,1
Inlined If-Else 6,3
Unsafe Boolean 5,4

Following is an overview of all the different algorithms:

1. Look-Up Table

This was the first program I came up with. It uses a simple
pre-calculated table to look up the value of any input character. As
expected it is pretty fast and it can also easily be extended to
support 'a'-'f' without performance loss.

Byte[] lookup = new byte[256];
byte counter = 0;
for(char c='0';c<='9';c++)
{ lookup[c] = counter;counter++;}
counter = 10;
for(char c='A';c<='F';c++)
{ lookup[c] = counter;counter++;}

for(int i=0;i<hexString.Length;i+=2)
Bytes[i>>1] = (byte)((lookup[hexString] << 4) +
lookup[hexString[i+1]]);


2. If-Else

Instead of using a look-up table the above program could easily be
modified by calling a method that calculates the correct value on the
spot. I was suprised when I noticed that this actually was faster than
looking up the value. The only disadvantage is that it suffers a large
performance hit, probably to the il not inlining, when extending to
handle 'a'-'f'

for(int i=0;i<hexString.Length;i+=2)
Bytes[i>>1] = (byte)((GetVal(hexString) << 4) +
GetVal(hexString[i+1]));

static int GetVal(char c){
if(c <= '9') return c - '0';
else return c - 'A' + 10;
}

3. Inlined If-Else

This is the same as the above program except that instead of calling a
function I calculate the value inside the for loop. This seems to
yield a slight performance increase. It is fast and versitile. It is
less readable than look-up table or ordinary if-else.

4. Boolean Logic

Avoiding jumps in the code can sometimes speed up program execution so
I decided to write a simple boolean version of GetVal. The efficency
was slightly lower than the other methods.

static int GetVal(char c){
return (c & 15) + ((c & 64) >> 3) + ((c & 64) >> 6);
}

5. Inlined Boolean Logic

Inlining boolean logic didn't seem to help. The IL compiler inline
seems to be working smothly already.

6. Unsafe Boolean Logic

In a final attempt to pull the most out of c# I decided to do an
unsafe version of boolean logic that accessed two letters at a time.
This proved to be the most efficent program, although not that
readable. Do not use unless maximum performance is needed.

fixed(char* c = hexString){
int* num = (int*) c;
for(int i=0;i<hexString.Length>>1;i++){
int t = (num & 983055) + ((num & 4194368) >> 3) + ((num &
4194368) >> 6);
t = t & 983055;
Bytes = (byte)((t << 4) | (t>>16));
}
}
 
R

Russell Mangel

This improved performance from 3500ms to 1116ms, nice.
Thanks for your input.
Russell Mangel

Chris A. R. said:
Just optimizing your current code can bring in some better results. For
"equivalence sake", I'm assuming you want all of the processing within the
outer for loop to be the same or there could be even more optimizations. By
the way, TickCount is NOT a high performance counter, so will not give you
very good differentiation in your results.

Int32 len = hexString.Length;
...
for(int k = 0; k < numLoops; k++)
{
System.Globalization.NumberStyles ns =
System.Globalization.NumberStyles.HexNumber;
for(int i=0; i < len; i+=2)
{
Bytes[i/2] = Byte.Parse( hexString.Substring(i, 2), ns );
}
}

Chris A.R.

Russell Mangel said:
The following code simply creates a byte array from a HexString.
Can anyone improve the perfomance of this method?

Thanks
Russell Mangel
Las Vegas, NV

String hexString = "AABBCCDDEEFF";
Byte[] Bytes = new byte[hexString.Length / 2];

Int32 len = Bytes.Length;

Int32 numLoops = 1000000;
Int32 start = System.Environment.TickCount;

for(int k = 0; k < numLoops; k++)
{
int j = 1;
for(int i=0; i < len; i++)
{
Bytes = Byte.Parse(hexString[j-1].ToString()+
hexString[j].ToString(),System.Globalization.NumberStyles.HexNumber);
j += 2;
}
}

// My P4 3Ghz Computer, does this in 3500 ms, can you do better?
Console.WriteLine("{0} ms", System.Environment.TickCount - start);

 
R

Russell Mangel

You slaughtered me.... almost like comparing an abacus to a
modern-day-calculator.
Thanks for your input, and excellent solution.

Russell Mangel

Jon Skeet said:
Russell Mangel said:
The following code simply creates a byte array from a HexString.
Can anyone improve the perfomance of this method?

Yup - I've got a version that's about 50 times as fast. It also doesn't
generate any garbage. It does rely on a lookup table which needs to be
created once, but that's a one-time hit.

I also investigated using a switch/case and just quick if/else clauses,
and while both were fast, this was the fastest.

Taking out the exception generation makes it even faster, but I wanted
to leave it in for correctness.

Here's my complete test code, including your version as well.

using System;

class Test
{
const int Iterations = 10000000;

static void Main()
{
// JIT the methods first
ParseRussell();
ParseJon();

// Now test them
DateTime start = DateTime.Now;
ParseRussell();
DateTime end = DateTime.Now;
Console.WriteLine ("Russell's implementation: {0}", end-start);
start = DateTime.Now;
ParseJon();
end = DateTime.Now;
Console.WriteLine ("Jon's implementation: {0}", end-start);
}

static readonly byte[] LookupTable;

static Test()
{
LookupTable = new byte[65536];
for (int i=0; i < 65536; i++)
{
LookupTable=255;
}
for (char c = '0'; c <= '9'; c++)
{
LookupTable[c]=(byte)(c-'0');
}
for (char c = 'a'; c <= 'f'; c++)
{
LookupTable[c]=(byte)(c-('a'-10));
}
for (char c = 'A'; c <= 'F'; c++)
{
LookupTable[c]=(byte)(c-('A'-10));
}
}

static void ParseJon()
{
String hexString = "AABBCCDDEEFF";
byte[] bytes = new byte[hexString.Length / 2];

int len = bytes.Length;

for(int k = 0; k < Iterations; k++)
{
int index=0;
for (int i=0; i < len; i++)
{
byte v1 = LookupTable[hexString[index++]];
byte v2 = LookupTable[hexString[index++]];
if (v1==255 || v2==255)
{
throw new FormatException ("Invalid hex string");
}

bytes=(byte)((v1<<4) + v2);
}
}
}

static void ParseRussell()
{
String hexString = "AABBCCDDEEFF";
Byte[] Bytes = new byte[hexString.Length / 2];

Int32 len = Bytes.Length;

Int32 numLoops = Iterations;

for(int k = 0; k < numLoops; k++)
{
int j = 1;
for(int i=0; i < len; i++)
{
Bytes = Byte.Parse(hexString[j-1].ToString()+
hexString[j].ToString(),
System.Globalization.NumberStyles.HexNumber);
j += 2;
}
}
}
}
 
R

Russell Mangel

(This is an old cliche, but I think it fits the situation.)

Back in 1965, a well known drill bit company sent one of their competitor's,
the world's smallest drill bit, or so they thought.

The competitor's using the power of collaboration, returned the drill bit to
the well known drill bit company.
On closer inspection, they discovered that a hole had been drilled through
the center of the drill bit!

Thanks for your ideas, and experience, I appreciate your information.
Russell Mangel

Marcus Andr?n said:
The following code simply creates a byte array from a HexString.
Can anyone improve the perfomance of this method?

I was bored and decided to do some general experimenting with this
problem. From the beginning I am assumed that the hexstring consists
only of numbers and capital letters. All algorithms expects wellformed
data and does not guarantee nice error handling. Some of the
algorithms could easily be transformed to handle more complex input
data though.

Before I continue I would also like to mention that when implementing
an optimized algorithm in production code it is recommended that you
have test cases that compares the result with a non optimized version
to make sure that no mistakes is made. Premature optimization is also
never a good idea.


Here is a list sorted by performance from worst to best (in seconds
for a number of iterations)

Original 528
Boolean 9,0
Inlined Boolean 8,9
Look-Up Table 7,9
If-Else 7,1
Inlined If-Else 6,3
Unsafe Boolean 5,4

Following is an overview of all the different algorithms:

1. Look-Up Table

This was the first program I came up with. It uses a simple
pre-calculated table to look up the value of any input character. As
expected it is pretty fast and it can also easily be extended to
support 'a'-'f' without performance loss.

Byte[] lookup = new byte[256];
byte counter = 0;
for(char c='0';c<='9';c++)
{ lookup[c] = counter;counter++;}
counter = 10;
for(char c='A';c<='F';c++)
{ lookup[c] = counter;counter++;}

for(int i=0;i<hexString.Length;i+=2)
Bytes[i>>1] = (byte)((lookup[hexString] << 4) +
lookup[hexString[i+1]]);


2. If-Else

Instead of using a look-up table the above program could easily be
modified by calling a method that calculates the correct value on the
spot. I was suprised when I noticed that this actually was faster than
looking up the value. The only disadvantage is that it suffers a large
performance hit, probably to the il not inlining, when extending to
handle 'a'-'f'

for(int i=0;i<hexString.Length;i+=2)
Bytes[i>>1] = (byte)((GetVal(hexString) << 4) +
GetVal(hexString[i+1]));

static int GetVal(char c){
if(c <= '9') return c - '0';
else return c - 'A' + 10;
}

3. Inlined If-Else

This is the same as the above program except that instead of calling a
function I calculate the value inside the for loop. This seems to
yield a slight performance increase. It is fast and versitile. It is
less readable than look-up table or ordinary if-else.

4. Boolean Logic

Avoiding jumps in the code can sometimes speed up program execution so
I decided to write a simple boolean version of GetVal. The efficency
was slightly lower than the other methods.

static int GetVal(char c){
return (c & 15) + ((c & 64) >> 3) + ((c & 64) >> 6);
}

5. Inlined Boolean Logic

Inlining boolean logic didn't seem to help. The IL compiler inline
seems to be working smothly already.

6. Unsafe Boolean Logic

In a final attempt to pull the most out of c# I decided to do an
unsafe version of boolean logic that accessed two letters at a time.
This proved to be the most efficent program, although not that
readable. Do not use unless maximum performance is needed.

fixed(char* c = hexString){
int* num = (int*) c;
for(int i=0;i<hexString.Length>>1;i++){
int t = (num & 983055) + ((num & 4194368) >> 3) + ((num &
4194368) >> 6);
t = t & 983055;
Bytes = (byte)((t << 4) | (t>>16));
}
}
 
R

Russell Mangel

He definately sleeps with a computer, and dreams of efficient assemby
language algorithms.
I like it!

Chris A. R. said:
I wish I had that much time on my hands! All I did was clean up the
code 'as-is' though I did think about using integer math as a faster way, as
you and Jon have done. There's an unsafe-code method I have in mind that
I'll try "if" I get time later.
However, this does point out that knowing precise methodology can help
prevent bottlenecks in code. That's what makes exercises such as these very
important for those who don't know these techniques, as well as refreshers
for those who do, but haven't had a need for such tight code recently.

Chris A.R.

Marcus Andr?n said:
The following code simply creates a byte array from a HexString.
Can anyone improve the perfomance of this method?

I was bored and decided to do some general experimenting with this
problem. From the beginning I am assumed that the hexstring consists
only of numbers and capital letters. All algorithms expects wellformed
data and does not guarantee nice error handling. Some of the
algorithms could easily be transformed to handle more complex input
data though.

Before I continue I would also like to mention that when implementing
an optimized algorithm in production code it is recommended that you
have test cases that compares the result with a non optimized version
to make sure that no mistakes is made. Premature optimization is also
never a good idea.


Here is a list sorted by performance from worst to best (in seconds
for a number of iterations)

Original 528
Boolean 9,0
Inlined Boolean 8,9
Look-Up Table 7,9
If-Else 7,1
Inlined If-Else 6,3
Unsafe Boolean 5,4

Following is an overview of all the different algorithms:

1. Look-Up Table

This was the first program I came up with. It uses a simple
pre-calculated table to look up the value of any input character. As
expected it is pretty fast and it can also easily be extended to
support 'a'-'f' without performance loss.

Byte[] lookup = new byte[256];
byte counter = 0;
for(char c='0';c<='9';c++)
{ lookup[c] = counter;counter++;}
counter = 10;
for(char c='A';c<='F';c++)
{ lookup[c] = counter;counter++;}

for(int i=0;i<hexString.Length;i+=2)
Bytes[i>>1] = (byte)((lookup[hexString] << 4) +
lookup[hexString[i+1]]);


2. If-Else

Instead of using a look-up table the above program could easily be
modified by calling a method that calculates the correct value on the
spot. I was suprised when I noticed that this actually was faster than
looking up the value. The only disadvantage is that it suffers a large
performance hit, probably to the il not inlining, when extending to
handle 'a'-'f'

for(int i=0;i<hexString.Length;i+=2)
Bytes[i>>1] = (byte)((GetVal(hexString) << 4) +
GetVal(hexString[i+1]));

static int GetVal(char c){
if(c <= '9') return c - '0';
else return c - 'A' + 10;
}

3. Inlined If-Else

This is the same as the above program except that instead of calling a
function I calculate the value inside the for loop. This seems to
yield a slight performance increase. It is fast and versitile. It is
less readable than look-up table or ordinary if-else.

4. Boolean Logic

Avoiding jumps in the code can sometimes speed up program execution so
I decided to write a simple boolean version of GetVal. The efficency
was slightly lower than the other methods.

static int GetVal(char c){
return (c & 15) + ((c & 64) >> 3) + ((c & 64) >> 6);
}

5. Inlined Boolean Logic

Inlining boolean logic didn't seem to help. The IL compiler inline
seems to be working smothly already.

6. Unsafe Boolean Logic

In a final attempt to pull the most out of c# I decided to do an
unsafe version of boolean logic that accessed two letters at a time.
This proved to be the most efficent program, although not that
readable. Do not use unless maximum performance is needed.

fixed(char* c = hexString){
int* num = (int*) c;
for(int i=0;i<hexString.Length>>1;i++){
int t = (num & 983055) + ((num & 4194368) >> 3) + ((num &
4194368) >> 6);
t = t & 983055;
Bytes = (byte)((t << 4) | (t>>16));
}
}

 
M

mikeb

Jon said:
Yup - I've got a version that's about 50 times as fast. It also doesn't
generate any garbage. It does rely on a lookup table which needs to be
created once, but that's a one-time hit.

I also investigated using a switch/case and just quick if/else clauses,
and while both were fast, this was the fastest.

Taking out the exception generation makes it even faster, but I wanted
to leave it in for correctness.

Jon, I played around with this (for far too much time), and I found it
difficult to improve on this with a better algorithm, but there's a
simple little change that gets another 5-8% improvement by taking
advantage of something the jitter optimizes specially:

If you change the inner loop's control statement from

for (int i=0; i < len; i++)

to

for (int i=0; i < bytes.Length; i++)

You get a speedup with no cost in readability. Mind you, it's a small
speedup (since the starting point is already pretty good), but it comes
at essentially no cost.

Apparently, when this idiom is used, the jitter eliminates the array
access bounds check for the bytes array in the for loop, since it can
tell from the for loop control statement that an out of bounds condition
will never occur.

See:


http://support.microsoft.com/default.aspx?scid=/servicedesks/webcasts/en/wc050102/wct050102.asp

for details.
Here's my complete test code, including your version as well.

using System;

class Test
{
const int Iterations = 10000000;

static void Main()
{
// JIT the methods first
ParseRussell();
ParseJon();

// Now test them
DateTime start = DateTime.Now;
ParseRussell();
DateTime end = DateTime.Now;
Console.WriteLine ("Russell's implementation: {0}", end-start);
start = DateTime.Now;
ParseJon();
end = DateTime.Now;
Console.WriteLine ("Jon's implementation: {0}", end-start);
}

static readonly byte[] LookupTable;

static Test()
{
LookupTable = new byte[65536];
for (int i=0; i < 65536; i++)
{
LookupTable=255;
}
for (char c = '0'; c <= '9'; c++)
{
LookupTable[c]=(byte)(c-'0');
}
for (char c = 'a'; c <= 'f'; c++)
{
LookupTable[c]=(byte)(c-('a'-10));
}
for (char c = 'A'; c <= 'F'; c++)
{
LookupTable[c]=(byte)(c-('A'-10));
}
}

static void ParseJon()
{
String hexString = "AABBCCDDEEFF";
byte[] bytes = new byte[hexString.Length / 2];

int len = bytes.Length;

for(int k = 0; k < Iterations; k++)
{
int index=0;
for (int i=0; i < len; i++)
{
byte v1 = LookupTable[hexString[index++]];
byte v2 = LookupTable[hexString[index++]];
if (v1==255 || v2==255)
{
throw new FormatException ("Invalid hex string");
}

bytes=(byte)((v1<<4) + v2);
}
}
}

static void ParseRussell()
{
String hexString = "AABBCCDDEEFF";
Byte[] Bytes = new byte[hexString.Length / 2];

Int32 len = Bytes.Length;

Int32 numLoops = Iterations;

for(int k = 0; k < numLoops; k++)
{
int j = 1;
for(int i=0; i < len; i++)
{
Bytes = Byte.Parse(hexString[j-1].ToString()+
hexString[j].ToString(),
System.Globalization.NumberStyles.HexNumber);
j += 2;
}
}
}
}
 
G

Guest

Hi Jon,

Thanks for your reply.

Yes, just want to inform Russell that Chris's solution may greatly increase
the performance. Although it is not the best solution. :)

I am glad that the community has provide so many replies for this issue.
Also, thank you for your information.

Best regards,
Jeffrey Tan
Microsoft Online Partner Support
Get Secure! - www.microsoft.com/security
This posting is provided "as is" with no warranties and confers no rights.
 
J

Jon Skeet [C# MVP]

mikeb said:
Jon, I played around with this (for far too much time), and I found it
difficult to improve on this with a better algorithm, but there's a
simple little change that gets another 5-8% improvement by taking
advantage of something the jitter optimizes specially:

If you change the inner loop's control statement from

for (int i=0; i < len; i++)

to

for (int i=0; i < bytes.Length; i++)

Ah yes - I meant to make that change (having originally copied the
framework from Russell's post). I didn't think it would make a 5-8%
improvement though - that's pretty significant...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top