Open UlyssesWu opened 6 months ago
Thank you for your report. I will consider this when I get around to it..
However, if you can, I would be grateful if you could provide me with Benchmark code or similar that can reproduce your problem. Thanks.
Code: (for demo I just read the same file for many times; for actual usage I'll read each asset in project)
using System.Diagnostics;
using VYaml.Serialization;
namespace VYamlBench
{
internal class Program
{
static async Task Main(string[] args)
{
var sw = Stopwatch.StartNew();
await Test();
sw.Stop();
Console.WriteLine($"Elapsed: {sw.ElapsedMilliseconds}ms");
}
static async Task Test()
{
var path = "Level.prefab";
await Parallel.ForAsync(0, 1000, async (_, token) =>
{
await using var fs = new FileStream(path,
new FileStreamOptions()
{ Access = FileAccess.Read, Options = FileOptions.Asynchronous | FileOptions.SequentialScan });
try
{
await YamlSerializer.DeserializeMultipleDocumentsAsync<dynamic>(fs, YamlSerializerOptions.Standard);
}
catch (Exception)
{
Console.WriteLine($"Parsing error");
}
});
}
}
}
YAML Sample: (borrowed from an open-source unity project) https://github.com/imengyu/Ballance/blob/main/Assets/Game/Levels/%E9%AD%94%E8%84%93%E7%A9%BA%E9%97%B4%E7%AB%99/Level.prefab
With v0.26.0: Elapsed: 42569ms
With v0.14.1: Elapsed: 33275ms
Here are the results of a run in my environment with the loop count set from 1000 to 100.
It's improved, but still worse than 0.14.1.
Test | 0.14.1 | 0.26.0 | with PR |
---|---|---|---|
VYamlBench (1000 loops) (ms) | 30803 | 43672 | 39051 |
My Actual Usage (min) | 2:07 | 4:00+ | 3:17 |
https://github.com/hadashiA/VYaml/blob/81abc25d9f5d8250028cf09d8a68a59a3d2cd649/VYaml/Internal/Scalar.cs#L11-L24
I have a tool to deserialize all assets from my unity project. It's basically calling
YamlSerializer.DeserializeMultipleDocumentsAsync
combined withParallel.ForEach
. When I upgraded to the latest VYaml (v0.26) I have observed very obvious performance lost. The process time increased from 1min to 4min.It seems that the recently imported
ConcurrentQueue<Scalar>.TryDequeue(...)
forScalarPool.Rent()
caused the problem.It's spending too much time on SpinWait. I guess the usage of
ConcurrentQueue
is thread safe but not multi-thread friendly. 🤔And, this is the time cost for the same input, before the
ConcurrentQueue
was introduced: