-
-
Notifications
You must be signed in to change notification settings - Fork 852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove Jpeg Huffman Decoder Bottleneck #643
Conversation
Codecov Report
@@ Coverage Diff @@
## master #643 +/- ##
==========================================
+ Coverage 89.16% 89.31% +0.14%
==========================================
Files 890 893 +3
Lines 37946 38020 +74
Branches 2661 2667 +6
==========================================
+ Hits 33835 33956 +121
+ Misses 3302 3267 -35
+ Partials 809 797 -12
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job, but I think the code is worth an other refactor/cleanup round before we move on.
It might be also worth to investigate if we can reduce the code duplications.
@@ -9,14 +9,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components | |||
[StructLayout(LayoutKind.Sequential)] | |||
internal unsafe struct FixedInt64Buffer18 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type name should be renamed accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
/// <summary> | ||
/// The collection of lookup tables used for fast AC entropy scan decoding. | ||
/// </summary> | ||
internal sealed class FastACTables : IDisposable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we really need this class in it's current form. Either we should hide the Table
property and encapsulate actual logic (initialization, retrieval of rows) inside the class, or we should drop it and define a helper method that creates Buffer2d<short>
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like having a class but I think you're right about the tables property. I'll hide that away and introduce a GetTableSpan()
method.
private byte marker; | ||
private bool badMarker; | ||
private long markerPosition; | ||
private int todo; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to have better names or some comments about the semantics of less trivial variables.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will do!
PdfJsFrameComponent component = this.components[k]; | ||
ref short blockDataRef = ref MemoryMarshal.GetReference(MemoryMarshal.Cast<Block8x8, short>(component.SpectralBlocks.Span)); | ||
ref PdfJsHuffmanTable dcHuffmanTable = ref dcHuffmanTables[component.DCHuffmanTableId]; | ||
ref PdfJsHuffmanTable acHuffmanTable = ref acHuffmanTables[component.ACHuffmanTableId]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
acHuffmanTable
and fastAC
are unused
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sometimes I miss Resharper.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got the unused, different line though so Github won't see it.
} | ||
} | ||
|
||
private void DecodeBlockProgressiveAC( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method is quite long, might be worth to refactor internal branches into separate methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll split out the Refinement part into a separate method.
private int PeekBits() => (int)((this.codeBuffer >> (32 - FastBits)) & ((1 << FastBits) - 1)); | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private uint LRot(uint x, int y) => (x << y) | (x >> (32 - y)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method can be static
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
/// Builds a lookup table for fast AC entropy scan decoding. | ||
/// </summary> | ||
/// <param name="index">The table index.</param> | ||
private void BuildFastACTable(int index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be probably a member of the FastACTables
class.
@@ -9,14 +9,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components | |||
[StructLayout(LayoutKind.Sequential)] | |||
internal unsafe struct FixedInt16Buffer18 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we rename the struct because it no longer is a short
/ Int16
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everything looks good for a merge now!
@JimBobSquarePants pushed some code simplification, and a benchmark to quickly test Baseline, Before:
Baseline, After:
|
Nice changes! That class looks very clean now and I like the inline and error helpers! How the hell does S.D decode the full stream so damn quickly, it's infuriating! |
Don't ask how, but it's possible to optimize huffman decoding with SIMD. |
I'm gonna merge this now to work on namespacing. |
Remove Jpeg Huffman Decoder Bottleneck
Prerequisites
Description
Replaces the slow PdfJsScanDecoder implementation with a much faster implementation based on Stb_Image. Now it's no longer a bottleneck. Fixes #601
We're creeping slowly closer to System.Drawing now for jpeg decoding.
New Benchmarks
Before Performance Trace
After Performance Trace
I'm genuinely amazed I managed to pull this off!