unity-experiment-framework icon indicating copy to clipboard operation
unity-experiment-framework copied to clipboard

Lag spikes from Trial.SaveData with large tracker files

Open soelderer opened this issue 9 months ago • 1 comments

I'm tracking data with 1kHz during trials which adds up easily to >8MB of GC Alloc and causes lag spikes in Trial.SaveDataTable:

Trial.End(): 9.5MB GC Alloc, Time 121ms, Self 4ms
Trial.SaveData: 7.6MB GC Alloc, Time 112ms, Self 0.6ms
Trial.SaveDataTable: 7.6MB GC Alloc, Time 107ms, Self 0.1ms
FileSaver.HandleDataTable: 7.6MB GC Alloc, Time 94ms, Self 0.4ms
UXFDataTable.GetCSVLines 7.6MB GC Alloc, Time 86ms, Self 76ms

Most of which is due to GetCSVLines(), because it allocates thousands of lines.

I suggest to move it to ManageInWorker(). I will try if that's possible and report back. I will also take a look if it's possible to optimize the loops etc.

Best, Paul

soelderer avatar Jul 22 '25 09:07 soelderer

Moving it to ManageInWorker reduced the time of Trial.End to around 36ms. The rest is largely a first-time JIT compilation spike. The second trial is already down to 10ms.

There are several functions with large Mono.JIT in the first trial:

  • SaveDataTable() with 15ms
  • HandleDataTable() with 5.3ms
  • SaveData() with 4.90ms

which is already 25ms of the 45ms lag spike. I suggest to prewarm Trial.SaveData() to precompile everything before the first trial.

Alternatively, one could switch to IL2CPP backend to get rid of JIT compilation. I couldn't get IL2CPP working. If you want to support it, I would open a separate feature request to discuss necessary steps. (The Linker complains about not finding Mono.Posix.dll (needed by System.Windows.Forms) in the StandaloneFileBrowser, which I had to manually copy to the Plugin folder. So there seems some work to be done. But I think it's worth it because precompilation makes sense in time-critical experiments).

soelderer avatar Jul 22 '25 10:07 soelderer