-
Notifications
You must be signed in to change notification settings - Fork 222
WIP: [[ Bugfix 21305 ]] Improve performance of stackfile saving on Windows #7319
base: develop
Are you sure you want to change the base?
Conversation
8adbaad
to
c220219
Compare
Okay so I think this is ready for review - I'm still slightly on the fence about including both metrics caching and the write buffer addition in 9.6. This definitely and without a doubt completely eliminates the difference in stackfile save speed between macOS and Windows; I also have a feeling it might significantly mitigate the issues with 'active' virus-scan technology too (although despite a lot of digging around that subject I have not managed to determine what exactly triggers them - but large numbers of WriteFile API calls seem to me, at least, to be a good guess). The metric caching is easy to assess correctness of, and even if there was a flaw it wouldn't be a disaster (the worse that would happen is that you might get the wrong UI font, or a DPI calc would be wrong). The other part - the write buffer addition needs more consideration - as if that is not correct (well at least as correct as before - see below) then that will cause stackfile corruption. The current This flaw has been in there forever (even before the MCSystemFileHandle interface was added!) and on all platforms and is due to The other two methods which cannot return an error are |
@mwieder It isn't wise to post comments on code in PRs which are marked as WIP as they can vanish from view (somewhat arbitrarily at times!). We use st-git (http://www.procode.org/stgit/) a lot internally to ensure well organised commits... Unfortunately, this means commit hashes are never stable back to the target/base branch and this causes issues for GitHub's tracking of source-level comments. Comments in the PR conversation for WIP things is fine though (as usual) :) |
@runrevmark no worries - I missed the WIP label there. |
@runrevmark GetFileSize could return an incorrect value if the file was opened in update mode. Aside from that I don't see any other problems 😉 |
@runrevmark I think you need a call to |
@runrevmark are we worried about successfully creating a write buffer that can never be written when the file is only opened in read mode? |
@montegoulding @montegoulding |
@livecodeian That is a very good point re update mode. Before changing the mechanism (I'll probably go for deferred error reporting) I'll double check whether GetFileSize is ever called when the stream is a stackfile write stream (as discussed above we probably want to limit the buffering to those types of streams for now). |
975c524
to
7a400d0
Compare
@livecodeian I think I've resolved the file size issue - it now computes the filesize as the max of (filesize + buffered-write-size) and (fileptr + buffered-write-size). I've also mitigated when write buffering will occur - restricting it to when stackfiles are being saved. @montegoulding I've made it so that write buffering is only performed when the file handle is created for a stream which is used for writing a stackfile so that should resolve the issue with the change in behavior on windows for 'write to file' syntax this would have caused otherwise. To resolve the latter I've added a new file open mode |
engine/src/dskw32.cpp
Outdated
if (this == IO_stdin) | ||
return true; // Shouldn't it return false??? | ||
|
||
if (m_handle == NULL) | ||
return false; | ||
|
||
/* If this is not a pipe then we may have a write buffer. */ | ||
if (!m_is_pipe) |
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.
@runrevmark I think you need && m_should_buffer_writes
here ?
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.
Oh! I can simplify that - I can set should_buffer_writes to false if the stream is a pipe. Thanks!
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.
@montegoulding That should be addressed now - I've changed this if to m_should_buffer_writes
, and only set the that to true if not a pipe in the constructor.
7a400d0
to
bc79fd3
Compare
@runrevmark shouldn't that be Alternatively you could just flush the buffer before getting the size |
bc79fd3
to
b146294
Compare
@livecodeian Yes - you are correct - think I've amended that now :) |
From a comment made by @montegoulding offline, I double checked the use of Marking this as WIP for now. |
This patch adds a very simple write buffer to the MCStdioFileHandle implementation on Win32. The write buffer is used on non-pipe handles and is initialized on first use of a write. The buffer has a fixed size of 64k, and a maximum single write size of 16k. Buffering writes causes a significant improvement in performance of stack serialization as that process results in a lot of 1, 2 and 4 byte individual writes. Additionally, a call to `MCS_flush` has been added after the end byte is written when serializing stackfiles. This ensures that if any buffered write data fails to be written, an error is generated and the original stackfile is not deleted. This specific change affects all platforms.
This patch adds a release note for bug 21305 where stackfile saving on Windows was considerably slower than other platforms.
b146294
to
bbdd925
Compare
I decided a modicum of caution was required here - so have split out the metrics caching into #7342. This needs a fair bit more work to be mergeable. |
The patch adds a simple write buffer to the Win32
MCStdioFileHandle
implementation. As serializing stacks usually involves a very large number of 1, 2 and 4 byte writes, the buffer vastly reduces the number ofWriteFile
Win32 API calls which are made.In order to ensure there aren't any problems with saving stackfiles if the write buffer does not flush on close, a call to
MCS_flush
has been added to the stackfile serialization code after the last terminating byte is written. This ensures that the original stackfile will not be removed until it is certain that the new stackfile is fully written.Note: The lack of a flush in the above case is actually a long standing 'hole' in stackfile saving. Whilst Windows did not have a engine-side write buffer, the
CloseHandle
API call could still fail, and the other platforms all used stdio FILE handles underneath which could also fail onfclose
.