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

Fix #33: Low performance due to GC on gzip/zlib writers #35

Merged
merged 3 commits into from
Oct 24, 2018

Conversation

jorygeerts
Copy link
Contributor

@jorygeerts jorygeerts commented Oct 12, 2018

Fix for #33

@jorygeerts
Copy link
Contributor Author

Note: the failed build for Go 1.6 and lower is due to a change in x/sys/unix, see golang/go#26576 for details.
I don't think this is something I broke nor something I can fix.

Copy link
Member

@gravis gravis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution!
I added some feedback and change requests.
Thank you!

gelf_writer.go Outdated
if w.gzipWriter == nil {
w.gzipWriter, err = gzip.NewWriterLevel(&zBuf, w.CompressionLevel)
}
w.gzipWriter.Reset(&zBuf)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if err is different from nil, this will crash since w is nil.

gelf_writer.go Outdated
switch w.CompressionType {
case CompressGzip:
zw, err = gzip.NewWriterLevel(&zBuf, w.CompressionLevel)
if w.gzipWriter == nil {
Copy link
Member

@gravis gravis Oct 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have a constructor (NewWriter), I suggest initializing in there instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, no, I just realized Writer is exported, so if someone has the great idea of instantiating it directly, zw becomes unset and unaccessible at the same time.

gelf_writer.go Outdated
@@ -30,6 +30,9 @@ type Writer struct {
Facility string // defaults to current process name
CompressionLevel int // one of the consts from compress/flate
CompressionType CompressType

gzipWriter *gzip.Writer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these fields are not exported, why don't we keep a single zw (io.WriteCloser) field instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Writer.CompressionType is exported, so to have a single "current writer" field would require checking that the writer type in that field is OK for the current CompressionType value. Something along the lines of changing if w.gzipWriter == nill to if w.zw == nill and w.zwCompressionType == w.CompressionType.

If that is the approach you prefer I'll add it.

Copy link
Contributor Author

@jorygeerts jorygeerts Oct 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taking another look at the code, Writer.CompressionLevel is also exported, so that needs to be checked before re-using a writer as well. Since storing a writer for every possible compression level isn't a good idea, I think if w.zw == nill and w.zwCompressionType == w.CompressionType and w.zwCompressionLevel == w.CompressionLevel is what we need.

I tried refactoring bufferedWriter into something that supports a Reset when I created this PR but couldn't get that to work. Since checking for CompressionType and CompressionLevel add more repetitive work (as does the err check you mentioned), I'll give that another go.

gelf_writer.go Outdated
if w.zlibWriter == nil {
w.zlibWriter, err = zlib.NewWriterLevel(&zBuf, w.CompressionLevel)
}
w.zlibWriter.Reset(&zBuf)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, check for err

@gravis
Copy link
Member

gravis commented Oct 24, 2018

This API is just awful. Having the writer exported, as well as most of the fields lead us to a lot of conditions and edge cases in the code. We should rewrite this in the future and bump a major version to break the API. Anyway, this is the best we can achieve on that foundation.
Thanks for your contribution.

Co-Authored-By: jorygeerts <[email protected]>
@gravis gravis merged commit 54c7b58 into gemnasium:master Oct 24, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants