-
Notifications
You must be signed in to change notification settings - Fork 207
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
Perf: use buffered streams for IO #307
Conversation
FileReader and FileWriter are not buffered, meaning they are slow. This change wraps the stream in a buffered reader/writer which in an (unscientific) unit test of the ErrorStore, reduced the write of an error from ~230ms to ~115ms. This also allows us to specify the charset encoding explicitly.
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.
Looks good from a perf standpoint - why is this a potential cause for serialization issues?
@kattrali it's very much a long shot but I thought it might be possible that some manufacturers don't use UTF-8 encoding by default, which is mandated by the Android docs. This change makes the use of UTF-8 explicit. However, thinking about it, if this were the cause, we would probably see various other issues as a result. |
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.
A couple of questions about closing
JsonStream stream = new JsonStream(new OutputStreamWriter(out)); | ||
Charset charset = Charset.forName("UTF-8"); | ||
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out, charset)); | ||
JsonStream stream = new JsonStream(writer); |
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.
do any of these other objects need to be closed
?
try { | ||
input = new FileReader(file); | ||
FileInputStream fis = new FileInputStream(file); | ||
input = new BufferedReader(new InputStreamReader(fis, "UTF-8")); |
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.
do any of these objects also need closing?
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 believe calling BufferedReader#close
also closes the InputStreamReader
, which in turn closes the FileInputStream
, which means that everything is automatically closed.
@@ -69,7 +72,8 @@ String write(@NonNull T streamable) { | |||
|
|||
Writer out = null; | |||
try { | |||
out = new FileWriter(filename); | |||
FileOutputStream fos = new FileOutputStream(filename); | |||
out = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8")); |
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.
do any of these objects also need closing?
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.
Addressed by other inline comment on JsonStream
@@ -69,7 +72,8 @@ String write(@NonNull T streamable) { | |||
|
|||
Writer out = null; | |||
try { | |||
out = new FileWriter(filename); | |||
FileOutputStream fos = new FileOutputStream(filename); | |||
out = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8")); | |||
|
|||
JsonStream stream = new JsonStream(out); | |||
stream.value(streamable); |
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.
not related to this PR but should we be closing this stream on the next line in the finally
block?
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.
Yes, that would make more sense than closing two separate streams. I've updated the PR so that we do this.
Close JsonStream rather than Writer, as this also closes the writer.
@martin308 thanks for the feedback! I've responded to the comments inline, and have also made a slight modification so that we close the |
Copied from #313 (addressing flaky tests) for extra context: Thanks for the review comments. I'm going to close this PR for now as I've noticed that #307 drastically reduces the flakiness of the tests on Travis (builds 3 times without incident), and I have another hypothesis about what may have caused the flakiness. I managed to intermittently reproduce the behaviour on an old emulator (API 16), and the log output suggests that other tests are constructing Passing output:
Failing output:
I think this is more of an issue with invalid assumptions made within our tests rather than anything sinister in the notifier. I'll create a ticket to investigate further which tests exactly are initialising Clients and causing this behaviour. |
} finally { | ||
IOUtils.closeQuietly(out); | ||
IOUtils.closeQuietly(stream); |
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 closing the JsonStream
close the OutputStream
as well? There's no explicit closing of the OutputStream
.
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.
Yes - also answered in previous comments in a bit more depth.
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.
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.
Ok, is this verifiable or testable at all? It seems like something that could change across implementations/versions.
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've added a test to check that JsonWriter closes its underlying stream - beyond that we'd just be testing the behaviour of the Java standard library.
Logger.info(String.format("Saved unsent payload to disk (%s) ", filename)); | ||
return filename; | ||
} catch (Exception exception) { | ||
Logger.warn(String.format("Couldn't save unsent payload to disk (%s) ", | ||
filename), exception); | ||
} finally { | ||
IOUtils.closeQuietly(out); | ||
IOUtils.closeQuietly(stream); |
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.
Same Q as above.
Support Unity shared object files in upload task
FileReader
andFileWriter
are not buffered, meaning they are slow. This change wraps all IO streams in a buffered reader/writer which in an (unscientific) unit test of the ErrorStore, reduced the write of an error from ~230ms to ~115ms.This also allows us to specify the charset encoding explicitly, which is a potential (but unproven) cause for File serialisation issues on devices from certain manufacturers.