Optimizing this code?

01/13/2014 11:58 Y u k i#1
PHP Code:
private static byte[] ReadPassword(byte[] raw)
        {
            
int x 0x14;
            
int y 0;
            
byte[] Pass = new byte[16];
            while (
0x24)
            {
                
Pass[y] = raw[x];
                
y++;
                
x++;
            }
            return 
Pass;
        } 
Probably like that?:

PHP Code:
private static byte[] ReadPassword(byte[] raw)
        {
            
int y 0;
            
byte[] Pass = new byte[16];
            for (
int X 0x140x24;x++)
            {
                
Pass[y] = raw[X];
                
y++;
            }
            return 
Pass;
        } 
Getting rid of y:

PHP Code:
private static byte[] ReadPassword(byte[] raw)
        {
            
byte[] Pass = new byte[16];
            for (
int X 0x140x24;x++)
            {
                
Pass[X-0x14] = raw[X];
            }
            return 
Pass;
        } 
Would that change anything? Im unsure about "for vs while"
01/13/2014 12:58 SteveRambo#2
Hint: don't try to do useless optimizations like this, unless you're 100% sure it's actually a bottleneck in your program, which I highly doubt is the case here.

Premature optimization is bad.
01/13/2014 13:52 KraHen#3
1. Make it work.
2. Make it work better.
01/13/2014 15:25 phize#4
Quote:
Originally Posted by SteveRambo View Post
Hint: don't try to do useless optimizations like this, unless you're 100% sure it's actually a bottleneck in your program, which I highly doubt is the case here.

Premature optimization is bad.
Søde pls
01/13/2014 17:00 Super Aids#5
Performing this:
Code:
Pass[X-0x14] = raw[X];
Is slower than this:
Code:
Pass[y] = raw[X];
y++;
Code:
Pass[X-0x14] = raw[X];
Would actually be something like this:
Code:
int index = (X - 0x14);
Pass[index] = raw[X];
So you're performing a mathematical operation that is not really needed, when you could just increase the value of y by 1.

Here is an actual optimization:
Code:
[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
		private static extern unsafe void* memcpy(void* dest, void* src, uint size);
		
		public static byte[] ReadPassord(byte[] raw)
		{
			byte[] Pass = new byte[16];
			
			unsafe
			{
				fixed (byte* src = raw, dest = Pass)
				{
					memcpy(dest, ((void*)(src + 0x14)), 16);
				}
			}
			
			return Pass;
		}
And if you want something even faster than memcpy:
[Only registered and activated users can see links. Click Here To Register...]
01/13/2014 17:35 CptSky#6
Quote:
Originally Posted by Y u k i View Post
PHP Code:
private static byte[] ReadPassword(byte[] raw)
        {
            
byte[] Pass = new byte[16];
            for (
int x 0x1400x24; ++x, ++y)
            {
                
Pass[y] = raw[x];
                
y++;
            }
            return 
Pass;
        } 
You can have both variables in the for-loop (not an optimization).
Post-incrementation will do a copy while pre-incrementation won't.

There is no point to do more optimization than that for 16 bytes, and for something that happens 1/1000th of time in the server.

Array.Copy / Buffer.Copy might be more optimized than your for-loop, but I doubt it will change anything.

In C++, if you would not matter accessing the raw data directly, I would just do « uint8_t* ptr = &raw[0x14] » and use it directly. No copy.

Quote:
Originally Posted by Super Aids View Post
[...]
Here is an actual optimization:
Code:
[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)]
		private static extern unsafe void* memcpy(void* dest, void* src, uint size);
		
		public static byte[] ReadPassord(byte[] raw)
		{
			byte[] Pass = new byte[16];
			
			unsafe
			{
				fixed (byte* src = raw, dest = Pass)
				{
					memcpy(dest, ((void*)(src + 0x14)), 16);
				}
			}
			
			return Pass;
		}
Not sure that adding the overhead of the native call and marshalling is really faster for 16 bytes...



Btw. More optimized memcpy than byte per byte in C#.
Code:
        /// <summary>
        /// Copies the values of num bytes from the location pointed by source directly to the memory block
        /// pointed by destination.
        ///
        /// The underlying type of the objects pointed by both the source and destination pointers are irrelevant
        /// for this function; The result is a binary copy of the data.
        /// </summary>
        /// <param name="dest">Pointer to the destination array where the content is to be copied.</param>
        /// <param name="src">Pointer to the source of data to be copied.</param>
        /// <param name="num">Number of bytes to copy.</param>
        /// <returns>The destination is returned.</returns>
        public static void* memcpy(void* dest, void* src, size_t num)
        {
            //The use of Int32 on both x86 and x64 is the best solution to get the best speed.
            //Probably due to the aligment of the data.

            Int32 amount = num / sizeof(size_t);
            for (Int32 i = 0; i < amount; ++i)
                ((size_t*)dest)[i] = ((size_t*)src)[i];

            amount = num % sizeof(size_t);

            Int32 pos = num - amount;
            for (Int32 i = 0; i < amount; ++i)
                (((Byte*)dest) + pos)[i] = (((Byte*)src) + pos)[i];

            return dest;
        }
01/13/2014 18:42 SteveRambo#7
Quote:
Originally Posted by CptSky View Post
Btw. More optimized memcpy than byte per byte in C#.
Code:
        /// <summary>
        /// Copies the values of num bytes from the location pointed by source directly to the memory block
        /// pointed by destination.
        ///
        /// The underlying type of the objects pointed by both the source and destination pointers are irrelevant
        /// for this function; The result is a binary copy of the data.
        /// </summary>
        /// <param name="dest">Pointer to the destination array where the content is to be copied.</param>
        /// <param name="src">Pointer to the source of data to be copied.</param>
        /// <param name="num">Number of bytes to copy.</param>
        /// <returns>The destination is returned.</returns>
        public static void* memcpy(void* dest, void* src, size_t num)
        {
            //The use of Int32 on both x86 and x64 is the best solution to get the best speed.
            //Probably due to the aligment of the data.

            Int32 amount = num / sizeof(size_t);
            for (Int32 i = 0; i < amount; ++i)
                ((size_t*)dest)[i] = ((size_t*)src)[i];

            amount = num % sizeof(size_t);

            Int32 pos = num - amount;
            for (Int32 i = 0; i < amount; ++i)
                (((Byte*)dest) + pos)[i] = (((Byte*)src) + pos)[i];

            return dest;
        }
I've never seen a size_t type in C#.
01/13/2014 19:39 CptSky#8
Quote:
Originally Posted by SteveRambo View Post
I've never seen a size_t type in C#.
Not a real type, just a wrapper...

Code:
        /// <summary>
        /// size_t corresponds to the integer data type returned by the language operator sizeof and is defined
        /// in the <cstdlib> header file (among others) as an unsigned integer type.
        /// </summary>
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public struct size_t
        {
            public Int32 value;

            public size_t(Int32 val) { value = val; }

            public static implicit operator Int32(size_t size)
            { return size.value; }
        }
        #endregion
01/13/2014 20:27 Super Aids#9
size_t is not actually a 32 bit integer. It depends on the computer architecture.
Also size_t has to be unsigned.

On x64 size_t would be an unsigned 64 bit integer.

However you can't do that correctly in C#, but it should at least be uint and not int.

[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...] -- same reference tho.
01/13/2014 20:42 SteveRambo#10
Quote:
Originally Posted by Super Aids View Post
size_t is not actually a 32 bit integer. It depends on the computer architecture.
Also size_t has to be unsigned.

On x64 size_t would be an unsigned 64 bit integer.

However you can't do that correctly in C#, but it should at least be uint and not int.

[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...] -- same reference tho.
You could use UIntPtr (which is an unsigned 32 bit integer on x86 and unsigned 64 bit integer on x64), or you could use your own conditional compilation symbols like:

Code:
        struct size_t
        {

#if x86 
            public UInt32 Value;
#elif x64
            public UInt64 Value;
#endif

        }
But yeah, I guess it should be an unsigned integer just like the documentation of the struct says: "and is defined in the <cstdlib> header file (among others) as an unsigned integer type.".

But for some stupid reason, the sizeof operator actually returns a signed integer in C#.
01/13/2014 21:38 Super Aids#11
Yeah I realized you could use that, but it would still have to be changed on every compilation :p
01/14/2014 04:57 CptSky#12
Quote:
Originally Posted by Super Aids View Post
size_t is not actually a 32 bit integer. It depends on the computer architecture.
Also size_t has to be unsigned.

On x64 size_t would be an unsigned 64 bit integer.

However you can't do that correctly in C#, but it should at least be uint and not int.

[Only registered and activated users can see links. Click Here To Register...]
[Only registered and activated users can see links. Click Here To Register...] -- same reference tho.
Yes, I know. But you all got the idea... And it was based on the fact that sizeof will return an int in C#, idem for .Length(). Plus, for the for-loop itself, the data is aligned on a 4-bytes boundary in both architectures.

It wasn't a pure C conversion.