Connecting Tech Pros Worldwide Help | Site Map

Representing a ulong as An Array of Bytes

AK_TIREDOFSPAM@hotmail.COM
Guest
 
Posts: n/a
#1: Aug 17 '06
I need to store a uint in an array of bytes. Doing it old fashioned
style works:

byte[] b=new byte[8];
ulong ul = 1;
for(int j=0; j<8; j++)
{
--- obviously I could (and did) optimize the code inside the loop
--- I just wanted to keep my example simple
b[7 - j] = (byte)((ul & bmask) >j*8);
bmask = bmask << 8;
}

It gives me exactly what I need:
b[0] = 0;
b[1] = 0;
(snip)
b[7] = 1;

I was trying to use MemoryStream and BinaryWriter and see how fast it
performs:

MemoryStream ms = new MemoryStream(16);
BinaryWriter br = new BinaryWriter(ms);

for(ulong i=1; i<3; i++)
{
br.Write(i);
}
byte[] b = ms.ToArray();

Unfortunately the order of bytes is not what I want:
b[0] = 1;
b[1] = 0;
b[2] = 0;
(snip)
b[7] = 0;

Is there any way to use canned classes like MemoryStream and
BinaryWriter and get the results that I got from my first snippet? The
reason I am asking is simple: canned classes might perform faster than
my homemade solution.

Greg Young
Guest
 
Posts: n/a
#2: Aug 17 '06

re: Representing a ulong as An Array of Bytes


Try the BitConverter class
http://msdn2.microsoft.com/en-us/library/d8z32tce.aspx should be the
overload you seek (for a ulong)

Cheers,

Greg Young
MVP - C# http://codebetter.com/blogs/gregyoung

<AK_TIREDOFSPAM@hotmail.COMwrote in message
news:1155831152.714042.185140@p79g2000cwp.googlegr oups.com...
Quote:
>I need to store a uint in an array of bytes. Doing it old fashioned
style works:
>
byte[] b=new byte[8];
ulong ul = 1;
for(int j=0; j<8; j++)
{
--- obviously I could (and did) optimize the code inside the loop
--- I just wanted to keep my example simple
b[7 - j] = (byte)((ul & bmask) >j*8);
bmask = bmask << 8;
}
>
It gives me exactly what I need:
b[0] = 0;
b[1] = 0;
(snip)
b[7] = 1;
>
I was trying to use MemoryStream and BinaryWriter and see how fast it
performs:
>
MemoryStream ms = new MemoryStream(16);
BinaryWriter br = new BinaryWriter(ms);
>
for(ulong i=1; i<3; i++)
{
br.Write(i);
}
byte[] b = ms.ToArray();
>
Unfortunately the order of bytes is not what I want:
b[0] = 1;
b[1] = 0;
b[2] = 0;
(snip)
b[7] = 0;
>
Is there any way to use canned classes like MemoryStream and
BinaryWriter and get the results that I got from my first snippet? The
reason I am asking is simple: canned classes might perform faster than
my homemade solution.
>

AK_TIREDOFSPAM@hotmail.COM
Guest
 
Posts: n/a
#3: Aug 17 '06

re: Representing a ulong as An Array of Bytes


Thank you Greg. I am comparing different ways to send a large array of
unsigned longs to SQL Server 2000. The solution needs to be very
performant. Among other alternatives, I am sending to the database an
image, as follows:

SqlCommand a = new SqlCommand("ImageTest", conn);
a.CommandType = System.Data.CommandType.StoredProcedure;
a.Parameters.Add(new SqlParameter("@image",
System.Data.SqlDbType.Image,2147483647));
-- b is an array of bytes
a.Parameters[0].Value = b;

My understanding is that BitConverter will create a new array of bytes
for every unsigned long, and I think that would be hard on the garbage
collector. My understanding is that most likely I will not notice that
in a short test on my local PC, but eventually in the production that
would cause a slowdown. So I estimate that in my situation it is better
to swap then bytes manually so that there are only 2 new objects as
opposed to 10001:

MemoryStream ms = new MemoryStream(80000);
BinaryWriter br = new BinaryWriter(ms);
for(ulong i=1; i<10001; i++)
{
br.Write(i);
}
byte[] b = ms.ToArray();
byte[] b1 = new byte[80000];
--- swap the bytes manually
for(k=0; k<80000; k+=8)
{
for(j=0; j<8; j++)
{
b1[k+7-j] = b[k+j];
}
}

Please correct me if I am wrong.

Greg Young
Guest
 
Posts: n/a
#4: Aug 17 '06

re: Representing a ulong as An Array of Bytes


Or you could just use a BinaryWriter and a memory stream .. the binary
writer actually does this in a more effiicient way than you do..

reflector'ed source of write method.

public virtual void Write(long value)
{
this._buffer[0] = (byte) value;
this._buffer[1] = (byte) (value >8);
this._buffer[2] = (byte) (value >0x10);
this._buffer[3] = (byte) (value >0x18);
this._buffer[4] = (byte) (value >0x20);
this._buffer[5] = (byte) (value >40);
this._buffer[6] = (byte) (value >0x30);
this._buffer[7] = (byte) (value >0x38);
this.OutStream.Write(this._buffer, 0, 8);
}


Cheers,

Greg Young
MVP - C#
http://codebetter.com/blogs/gregyoung

<AK_TIREDOFSPAM@hotmail.COMwrote in message
news:1155835940.117869.197730@75g2000cwc.googlegro ups.com...
Quote:
Thank you Greg. I am comparing different ways to send a large array of
unsigned longs to SQL Server 2000. The solution needs to be very
performant. Among other alternatives, I am sending to the database an
image, as follows:
>
SqlCommand a = new SqlCommand("ImageTest", conn);
a.CommandType = System.Data.CommandType.StoredProcedure;
a.Parameters.Add(new SqlParameter("@image",
System.Data.SqlDbType.Image,2147483647));
-- b is an array of bytes
a.Parameters[0].Value = b;
>
My understanding is that BitConverter will create a new array of bytes
for every unsigned long, and I think that would be hard on the garbage
collector. My understanding is that most likely I will not notice that
in a short test on my local PC, but eventually in the production that
would cause a slowdown. So I estimate that in my situation it is better
to swap then bytes manually so that there are only 2 new objects as
opposed to 10001:
>
MemoryStream ms = new MemoryStream(80000);
BinaryWriter br = new BinaryWriter(ms);
for(ulong i=1; i<10001; i++)
{
br.Write(i);
}
byte[] b = ms.ToArray();
byte[] b1 = new byte[80000];
--- swap the bytes manually
for(k=0; k<80000; k+=8)
{
for(j=0; j<8; j++)
{
b1[k+7-j] = b[k+j];
}
}
>
Please correct me if I am wrong.
>

Jon Skeet [C# MVP]
Guest
 
Posts: n/a
#5: Aug 17 '06

re: Representing a ulong as An Array of Bytes


<AK_TIREDOFSPAM@hotmail.COMwrote:
Quote:
I need to store a uint in an array of bytes.
See http://www.pobox.com/~skeet/csharp/miscutil

It provides:
1) A BinaryWriter that lets you specify the endianness
2) A BitConverter that lets you specify the endianness *and convert
into an existing array*

They may well not be faster than your original solution, but I strongly
suspect that talking to SQL server is going to be a bottleneck long
before this is. What are your performance requirements for this section
of the code, and how do current solutions compare with it?

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
AK_TIREDOFSPAM@hotmail.COM
Guest
 
Posts: n/a
#6: Aug 17 '06

re: Representing a ulong as An Array of Bytes


Or you could just use a BinaryWriter and a memory stream .. the binary
Quote:
writer actually does this in a more effiicient way than you do..
>
reflector'ed source of write method.
>
public virtual void Write(long value)
{
this._buffer[0] = (byte) value;
this._buffer[1] = (byte) (value >8);
this._buffer[2] = (byte) (value >0x10);
this._buffer[3] = (byte) (value >0x18);
this._buffer[4] = (byte) (value >0x20);
this._buffer[5] = (byte) (value >40);
this._buffer[6] = (byte) (value >0x30);
this._buffer[7] = (byte) (value >0x38);
this.OutStream.Write(this._buffer, 0, 8);
}
>
Thanks Greg, this code snippet really helped. In fact, I don't see any
advantage of using a memory stream. It's so simple:

static byte[] UlongsToBytes(ulong[] ulongs)
{
int ifrom = ulongs.GetLowerBound(0);
int ito = ulongs.GetUpperBound(0);
int l = (ito - ifrom + 1)*8;
byte[] ret = new byte[l];
int retind = 0;
for(int i=ifrom; i<ito; i++)
{
ulong v = ulongs[i];
ret[retind++] = (byte) (v >0x38);
ret[retind++] = (byte) (v >0x30);
ret[retind++] = (byte) (v >40);
ret[retind++] = (byte) (v >0x20);
ret[retind++] = (byte) (v >0x18);
ret[retind++] = (byte) (v >0x10);
ret[retind++] = (byte) (v >8);
ret[retind++] = (byte) v;
}

return ret;
}

Am I missing something? Why should I use a memory stream?

AK_TIREDOFSPAM@hotmail.COM
Guest
 
Posts: n/a
#7: Aug 17 '06

re: Representing a ulong as An Array of Bytes


>
Quote:
See http://www.pobox.com/~skeet/csharp/miscutil
>
It provides:
1) A BinaryWriter that lets you specify the endianness
2) A BitConverter that lets you specify the endianness *and convert
into an existing array*
>
They may well not be faster than your original solution, but I strongly
suspect that talking to SQL server is going to be a bottleneck long
before this is. What are your performance requirements for this section
of the code, and how do current solutions compare with it?
>
Thanks Jon, reading the sources was very interesting. The performance
requirements are simple: it must work faster than the competitors'
solutions.

Greg Young
Guest
 
Posts: n/a
#8: Aug 18 '06

re: Representing a ulong as An Array of Bytes


Well ...

1) the memory stream automatically will size itself ..
2) you can just use a BinaryWriter ... that code is reflector'ed from the
BinaryWriter class .. Why write it yourself?

Cheers,

Greg Young
MVP - C#
http://codebetter.com/blogs/gregyoung

<AK_TIREDOFSPAM@hotmail.COMwrote in message
news:1155849702.274532.263620@b28g2000cwb.googlegr oups.com...
Quote:
Quote:
>Or you could just use a BinaryWriter and a memory stream .. the binary
>writer actually does this in a more effiicient way than you do..
>>
>reflector'ed source of write method.
>>
>public virtual void Write(long value)
>{
> this._buffer[0] = (byte) value;
> this._buffer[1] = (byte) (value >8);
> this._buffer[2] = (byte) (value >0x10);
> this._buffer[3] = (byte) (value >0x18);
> this._buffer[4] = (byte) (value >0x20);
> this._buffer[5] = (byte) (value >40);
> this._buffer[6] = (byte) (value >0x30);
> this._buffer[7] = (byte) (value >0x38);
> this.OutStream.Write(this._buffer, 0, 8);
>}
>>
>
Thanks Greg, this code snippet really helped. In fact, I don't see any
advantage of using a memory stream. It's so simple:
>
static byte[] UlongsToBytes(ulong[] ulongs)
{
int ifrom = ulongs.GetLowerBound(0);
int ito = ulongs.GetUpperBound(0);
int l = (ito - ifrom + 1)*8;
byte[] ret = new byte[l];
int retind = 0;
for(int i=ifrom; i<ito; i++)
{
ulong v = ulongs[i];
ret[retind++] = (byte) (v >0x38);
ret[retind++] = (byte) (v >0x30);
ret[retind++] = (byte) (v >40);
ret[retind++] = (byte) (v >0x20);
ret[retind++] = (byte) (v >0x18);
ret[retind++] = (byte) (v >0x10);
ret[retind++] = (byte) (v >8);
ret[retind++] = (byte) v;
}
>
return ret;
}
>
Am I missing something? Why should I use a memory stream?
>

Jon Skeet [C# MVP]
Guest
 
Posts: n/a
#9: Aug 18 '06

re: Representing a ulong as An Array of Bytes


<AK_TIREDOFSPAM@hotmail.COMwrote:
Quote:
Thanks Jon, reading the sources was very interesting. The performance
requirements are simple: it must work faster than the competitors'
solutions.
Presumably that's an *overall* requirement though, not a requirement of
this particular piece of the code. Have you measured how much of the
time is spent converting ulongs to arrays of bytes?

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jon Skeet [C# MVP]
Guest
 
Posts: n/a
#10: Aug 18 '06

re: Representing a ulong as An Array of Bytes


Greg Young <druckdruckREMOVEgoose@hotmail.comwrote:
Quote:
1) the memory stream automatically will size itself ..
2) you can just use a BinaryWriter ... that code is reflector'ed from the
BinaryWriter class .. Why write it yourself?
Check the differences between the code you posted and the version the
OP just posted - the endianness is different.

--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Greg Young
Guest
 
Posts: n/a
#11: Aug 18 '06

re: Representing a ulong as An Array of Bytes


Right you are.
"Jon Skeet [C# MVP]" <skeet@pobox.comwrote in message
news:MPG.1f4f6193ae4c414198d3e5@msnews.microsoft.c om...
Quote:
Greg Young <druckdruckREMOVEgoose@hotmail.comwrote:
Quote:
>1) the memory stream automatically will size itself ..
>2) you can just use a BinaryWriter ... that code is reflector'ed from the
>BinaryWriter class .. Why write it yourself?
>
Check the differences between the code you posted and the version the
OP just posted - the endianness is different.
>
--
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too

AK_TIREDOFSPAM@hotmail.COM
Guest
 
Posts: n/a
#12: Aug 18 '06

re: Representing a ulong as An Array of Bytes


>
Quote:
Presumably that's an *overall* requirement though, not a requirement of
this particular piece of the code. Have you measured how much of the
time is spent converting ulongs to arrays of bytes?
>
Jon,

Your point is taken. You are correct - the time on the client side is
negligible either way.

AK_TIREDOFSPAM@hotmail.COM
Guest
 
Posts: n/a
#13: Aug 18 '06

re: Representing a ulong as An Array of Bytes


Thanks Greg

Closed Thread


Similar C# / C Sharp bytes