ForeverZer0 / SharpNBT

A pure CLS-compliant C# implementation of the Named Binary Tag (NBT) format specification commonly used with Minecraft applications, allowing easy reading/writing streams and serialization to other formats.
MIT License
25 stars 9 forks source link

Wrapping deflated streams in BufferedStream when reading #29

Closed Sitterr closed 4 months ago

Sitterr commented 4 months ago

Seems that by default ZLibStream and GZipStream don't buffer themselves when decompressing so reading in small chunks(which is the case with nbt tags) is not good for performance https://github.com/dotnet/runtime/issues/39233

The speed of NbtFile.Read() that I measured:

ForeverZer0 commented 4 months ago

I am very much in favor of the concept of this PR, but I notice there is an issue in the implementation that needs to first be corrected: the underlying stream will not get disposed.

Perhaps the constructor of TagReader might be a more suitable place to wrap it, and provide more flexibility if a user is providing their own stream.

Just a rough-draft concept, but something akin to this was my first thought:

This is likely going to require the introduction of a new variable to store the stream we wrap, as the BufferedStream would become the BaseStream value, which is stored as an abstract Stream type.

ForeverZer0 commented 4 months ago

I took a look at the source code for BufferedStream, and it appears to call close on the underlying stream,.

It appears to call Close, but not Dispose on the underlying stream. This is probably enough to forget my previous reply and simply merge your PR as-is. The Dispose is a bit superfluous, and will get called by the finalizer anyways, which in turn just ensures that Close was called. Close is what actually frees the resources and releases the handle.