0

I programming in C#.

I am looking for efficient way to set double (or any primitive) value into exist byte array in specific offset. I am familiar with BitConverter.GetBytes and the Buffer.BlockCopy command. I am looking for function that enable my to set the primitive value directly to specific byte offset in the array, without new memory allocation Something like this code

public unsafe static void  SetBytes(int value,byte[] output,int index)
    {
        fixed(byte* b = output)
            *((int*)b+index) = value;

    }

The regular version:

 public unsafe static void SetBytesArray(int value, byte[] output, int index)
        {
            byte[] byteValue = BitConverter.GetBytes(value);
            Buffer.BlockCopy(byteValue, 0, output, index * 4, 4);
        }

The friends in the forum ask me to add measure compression between the extreme version above , and to regular version

I create array of 1000 bytes, In each cycle I fill all the array with constant int value. I repeat on the above action for 10000 times , I measure the time with StopWatch.

Avg time for one cycle:

  1. extreme - 0.004 ticks (SetBytes)

  2. regular - 0.028 ticks (SetBytesArray)

Thanks,

Mak

MAK
  • 605
  • 9
  • 19
  • So you have some buffer `output` and at position `index` you want to overwrite the next 4 bytes with the value `value`? Are you sure you need `unsafe` and `fixed` for this? Why not break `value` into 4 `byte` values and overwrite those indexes of `output`? – JamesFaix Apr 18 '18 at 15:21
  • Because to do that is not efficient Enough , GetBytes of any other option allocate new memory in every step, I am working in real time ,in high speed with high volume data. – MAK Apr 18 '18 at 15:21
  • You just need to do unchecked{ output[index] = byte1, output[index+1]=byte2 .... } - that will be most efficient way – Evgeny Gorbovoy Apr 18 '18 at 15:33
  • It would be interesting to have two versions of this. One that uses Array Copy and Array SetByte and one that uses your extreme version. You could measure the difference in your specific scenario from a repeatable test. – Sql Surfer Apr 18 '18 at 15:40
  • 1
    Not sure what the hangup might be, but the posted snippet does have a bug. The index variable does not act as a byte index, it indexes ints. Use byte* b = &output[index] instead. – Hans Passant Apr 18 '18 at 16:13
  • @SqlSurfer I add compare for the extreme version and the regular one. – MAK Apr 19 '18 at 07:46

1 Answers1

1

As far as I can see, what you have should work (once you've fixed up the compile error).

For example:

using System;
using System.Linq;

namespace Demo
{
    class Program
    {
        static void Main()
        {
            byte[] data = new byte[16];
            int value = 0x12345678;
            SetBytes(value, data, 5);

            // This prints "0, 0, 0, 0, 0, 78, 56, 34, 12, 0, 0, 0, 0, 0, 0, 0"
            Console.WriteLine(string.Join(", ", data.Select(b => b.ToString("x"))));
        }

        public static unsafe void SetBytes(int value, byte[] output, int index)
        {
            fixed (byte* b = output)
                *((int*)(b + index)) = value;
        }
    }
}

[EDIT: Changed to work with byte offset rather than int offset]

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • Yes, I notice that only now :-) .But I am looking for index offset in byte not in int, you have any suggestion ? – MAK Apr 18 '18 at 15:38
  • @MAK Sorry, went home for the day! To make it use a byte index you just need to change it to `*((int*)(b + index)) = value;` – Matthew Watson Apr 19 '18 at 07:40