Skip to content
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

Reduce overhead reading byte/sbyte arrays from IndexedReader #405

Merged
merged 1 commit into from
Feb 6, 2024

Conversation

drewnoakes
Copy link
Owner

Traces gathered over the test suite show:

  • ~2.7% CPU spent in IndexedReader.GetByte(int)
  • ~0.4% CPU spent in IndexedReader.GetSByte(int)

image

image

Looking at the main callers shows loops in TiffReader that call these methods in loops. This approach accrues overhead per-byte due to bounds checking and virtual dispatch.

Instead, use the Span<byte> overload of GetBytes that performs the bounds checking once, then copies data in a single call.

It may be possible to give a similar treatment to the handling of other TIFF format codes, though they're not currently showing up on traces and would be more complex to implement due to byte-ordering issues (byte and sbyte being immune from those).

Traces gathered over the test suite show:

- ~2.7% CPU spent in `IndexedReader.GetByte(int)`
- ~0.4% CPU spent in `IndexedReader.GetSByte(int)`

Looking at the main callers shows loops in `TiffReader` that call these methods in loops. This approach accrues overhead per-byte due to bounds checking and virtual dispatch.

Instead, use the `Span<byte>` overload of `GetBytes` that performs the bounds checking once, then copies data in a single call.

It may be possible to give a similar treatment to the handling of other TIFF format codes, though they're not currently showing up on traces and would be more complex to implement due to byte-ordering issues (`byte` and `sbyte` being immune from those).
@iamcarbon
Copy link
Collaborator

Looks good!

@drewnoakes
Copy link
Owner Author

Once these changes are in I'll gather some new traces and see what surfaces.

We're so IO-bound that I think we'll need to rethink how we read from disk/network to get much more improvement on the perf side.

@drewnoakes drewnoakes merged commit 1837bff into main Feb 6, 2024
2 checks passed
@drewnoakes drewnoakes deleted the reduce-reader-get-byte-overhead branch February 6, 2024 22:10
@drewnoakes
Copy link
Owner Author

We're so IO-bound that I think we'll need to rethink how we read from disk/network to get much more improvement on the perf side.

As part of that a good goal would be to enable async IO so that we're not blocking threads on IO operations. The way we currently read data, byte-by-byte, doesn't lend itself well to that much async, as the overhead adds up. I lean towards async IO for pulling larger chunks of data from the file, storing those chunks as Memory<byte> types, and then moving parsing to subsequent steps (non-IO).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants