Let's break down your steps, and try to make each step as efficient as possible (by efficient, we want to not copy data if we don't have to, and when we do, we copy it using the most efficient method).
Sending a byte[] inputBuffer into a function
That part is simply passing in the array, which does not do a copy of the array, just a copy of the array reference (and that won't even happen if .NET has inlined the method call).
void DoStuff(byte[] inputBuffer)
{
...
In that function I need to parse the array for e.g.
inputBuffer = {1A,2B,3C,4D,5F,6E,2A,3B,4C,6D}
Let's say your inputBuffer looks like {00, 00, 1A,2B,3C,4D,5F,6E,2A,3B,4C,6D, 00, 00}
then your parse/find would get the start and end index of the above array of bytes as 2 and 11, for a length of 10.
I want to read 1A ,2B and 3C first
Then 4D,5F,6E,2A,3B,4C,6D second
You can slice the array twice, creating two ReadOnlySpan<byte>
, which use the underlying memory directly (no copying). (see this reference for more info).
var firstSlice = new ReadOnlySpan<byte>(inputBuffer, 2, 3); // index 2, for 3 bytes
var secondSlice = new ReadOnlySpan<byte> inputBuffer, 5, 7); // index 5 for 7 bytes
I need to use these two subarrays to do some operations (Hash and Encrypt them)
Do your hashing and encryption on these spans; this doesn't change the spans, so you're still using the in-place memory. If your hash/encryption routines can accept arrays with offsets, then you won't even need to give them the span treatment.
Then I need to put them back into a new array with some extra bytes attach to it (length bytes)
I don't want to use blockcopy since I don't think it's really efficient
You simply need to create the array,
var result = new byte[10 + size-of-extra-data];
and copy the two slices and the extra data into that array using either Buffer.BlockCopy
, Array.Copy
a loop over bytes, or an unrolled loop. (Note: if it's thread-safe, and you're working with same-size data each time, you can avoid the above allocation by reusing a preallocated result array).
Anyway, for your specific case (and by the way, benchmark it if it's in critical code), it seems like a loop or unrolled loop (which .NET will probably unroll anyway when optimizing the code) is your best bet.
// this could be a loop, but I'm unrolling it here...
result[0] = firstSlice[0];
result[1] = firstSlice[1];
result[2] = firstSlice[2];
result[3] = secondSlice[0];
result[4] = secondSlice[1];
result[5] = secondSlice[2];
result[6] = secondSlice[3];
result[7] = secondSlice[4];
result[8] = secondSlice[5];
result[9] = secondSlice[6];
... // copy extra data from wherever it comes from
With your next best option being Array.Copy
// just one copy since we are using the original source; it would be two if we used the spans
Array.Copy(inputBuffer, 2, result, 0, 10);
// now copy in the extra data
Array.Copy(extraData, 0, result, 10, extraData.Length);
or, with a similar signature, the Buffer.BlockCopy:
// just one copy since we are using the original source; it would be two if we used the spans
Buffer.BlockCopy(inputBuffer, 2, result, 0, 10);
// now copy in the extra data
Buffer.BlockCopy(extraData, 0, result, 10, extraData.Length);
The reference for the above assertions of efficiency comes from this highly upvoted SO answer.