SteveLillis / .NET-Ogg-Vorbis-Encoder

Ogg Vorbis audio encoding library written in C#
MIT License
69 stars 16 forks source link

Optimizations #11

Closed cabauman closed 3 years ago

cabauman commented 3 years ago

This PR improves both speed and memory performance. It's about twice as fast and uses about 1/4 the amount of memory. I know the PR is kind of big but it's pretty simple to review if you check the diff of each commit separately. The BenchmarkDotNet project is included in the first commit. I had to bump the target frameworks up (net35 -> net45 & netstandard1.0 -> netstandard1.1) in order to support adding the System.Memory nuget package for Span<T> and MemoryPool<T>.

I'm as big a fan of interface abstraction as anybody, but unfortunately the performance of IList indexer is extremely bad in a hot path. So much so in this case that simply changing IList to concrete types (array and OffsetArray) doubles the speed.

The biggest memory hog was FloatExtensions.ToDecibel. It's one of the most called methods in the entire project and it allocates a new 4 byte array every single time.

Here are the benchmark results for each of the four commits. I used the same code as in the example project and extracted a 30s clip out of the original unencoded.raw file.

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.1082 (1909/November2018Update/19H2) Intel Core i5-4200U CPU 1.60GHz (Haswell), 1 CPU, 4 logical and 2 physical cores .NET Core SDK=5.0.100-rc.1.20452.10 [Host] : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT DefaultJob : .NET Core 3.1.9 (CoreCLR 4.700.20.47201, CoreFX 4.700.20.47203), X64 RyuJIT

Original

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
ConvertPCMFile 4.174 s 0.0828 s 0.1835 s 395000.0000 1000.0000 - 608.78 MB


After commit 2: Change IList parameters to concrete types (array and OffsetArray)

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
ConvertPCMFile 1.800 s 0.0374 s 0.1074 s 395000.0000 1000.0000 - 608.91 MB


After commit 3: Use Span instead of OffsetArray Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
ConvertPCMFile 1.800 s 0.0566 s 0.1625 s 394000.0000 1000.0000 - 607.25 MB


After commit 4: Add stackalloc and MemoryPool optimizations Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
ConvertPCMFile 1.605 s 0.0374 s 0.1073 s 107000.0000 1000.0000 - 162.53 MB


Let me know if you have any questions, concerns, or requests. Thanks for this great library!

SteveLillis commented 3 years ago

Hi!

Sorry I've taken so long to see this. It's a great change and has been mentioned in various issues. I'm inviting you to be a contributor as I no longer actively maintain this project.

Cheers,

Steve

cabauman commented 3 years ago

Not a problem at all @SteveLillis . And thanks, I'd be happy to become a contributor.