- I am working with parallel job.
- The target is decoding a lot of binary data files with the power of multithread.
- Assume each file is a
byte[]
with around 7~10 Megabytes after decoded. - The problem is I don’t know the exact size of decoded data until it gets decoded, so I have to use
UnsafeList
instead ofNativeArray
for the output. - But
UnsafeList
doesn’t provide any direct conversion to/fromarray[]
, then I loop among huge iteration to append each byte of the data. It slows my device alot, are there any proper way?
Here is the sample codes:
- data structure.
public struct InputData
{
[ReadOnly] public NativeArray<byte> encoded;
}
public struct OutputData
{
[WriteOnly] public int index;
// I want to use NativeArray instead, but the Job doesn't allow Allocator.Persistent for NativeArray.
// I need the data allocated in Persistent to be process later in the main thread
[WriteOnly] public UnsafeList<byte> decoded;
}
- job structure. Assume that the job is scheduled and works properly.
[BurstCompile]
public struct DecodeDataJob : IJobParallelFor
{
// this nested NativeArray inside UnsafeList
// UnsafeList<InputData> has been allocated when schedule job
[ReadOnly] public UnsafeList<InputData> inputs;
// this nested UnsafeList inside UnsafeList
// UnsafeList<OutputData> has been allocated when schedule job
[WriteOnly] public UnsafeList<OutputData>.ParallelWriter outputWriter;
public void Execute(int index)
{
InputData anInput = inputs[index];
// this shows warning: NativeArray ToArray() contain managed types
byte[] arrayInput = anInput.encoded.ToArray();
// this also shows warning: contain managed types
byte[] arrayOutput = DecodeData(arrayInput);
// - Are there better way to convert byte[] to UnsafeList<byte>? -
UnsafeList<byte> output = new UnsafeList<byte>(arrayOutput.Length, Allocator.Persistent);
for (int i = 0; i < arrayOutput.Length; ++i)
{
output.AddNoResize(arrayOutput[i]);
}
OutputData anOutput = new OutputData()
{
index = index,
decoded = output
};
outputWriter.AddNoResize(anOutput);
}
// this function is from a library, which I can't change the input and output
private static byte[] DecodeData(byte[] input) { }
}
- managed class for post process.
public class ProcessDecodedDataInManaged
{
public void ParseDecodedFiles(in UnsafeList<OutputData> outputs)
{
for (int i = 0; i < outputs.Length; ++i)
{
OutputData anOutput = outputs[i];
byte[] arrayOutput = this.ConvertUnsafeListToArray(anOutput.decoded);
anOutput.decoded.Dispose();
ProcessDecoded(arrayOutput);
}
}
private byte[] ConvertUnsafeListToArray(in UnsafeList<byte> input)
{
byte[] result = new byte[input.Length];
for (int i = 0; i < result.Length; ++i)
{
result[i] = input[i];
}
return result;
}
// this function is from a library, which I can't change the input and output
private static void ProcessDecoded(byte[] decoded) { }
}
The ConvertUnsafeListToArray
causes a huge drop in performance with just 7 files.
For 42 files, it hanged.