-
-
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
GFile: read/write with fa.*_buffer #528
Conversation
1b1ff33
to
f6741ce
Compare
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-528 |
@@ -1,119 +0,0 @@ | |||
/* |
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.
Please revert this deletion.
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.
Ah, I see! This looked like an accident. A short comment would have helped here 🙂
Thanks for the PR! Out of curiosity, did you notice any speedups? |
Hmm, there's something strange: it's still slow, and my implementation is still ~25x faster. To find out what's going on, I hardcoded the length (because I know the size of my file): -let length = self.fa.get_length();
+let length = 8431328; // the evilest thing ever ...and got ~22x performance boost. 🤯 Is |
@Bromeon Tested with itest benchmarks with New impl:
Old impl:
Edit: even now the speedup in New impl:
Old impl:
@andreymal Will test out if |
Thanks to both of you for the measurements! 👍 Godot docs also recommend the Can we theoretically cache length? Writing would invalidate the cache. |
@Bromeon Not only recommend, but actually practically enforces. I've copy-pasted the implementation provided by @andreymal and with out
The error 18 means "EOF". So I think I need to go back to the writing board and cache the file length. Better than caching position, for sure :) You can move open file in read/write mode and the file length could potentially change only during write, potentially checking the other conditions (stored value length > file lenght - cursor position) would be overshoot. Intermediate read and write operations are usually problematic, I think this strategy will be good either way. As we already try to enforce unique reference to FA, I think if the user tries to open and write to the same file with different @andreymal I see, the |
@StatisMike I found a bug in |
(However, if |
Strange, you didn't receive the error I pasted from itest results while using your implementation provided in #513 (comment) ? The failing test tries to read file to the end: Edit: Addition of |
@StatisMike reaching EOF after calling (and yes, I didn't notice this in my implementation because my project never reaches EOF. Well, my bad 🙃) (UPD2: I added |
@andreymal Oh, the source of my mistake was the Godot docs that didn't point to ERR_FILE_EOF as not being an error: https://docs.godotengine.org/en/stable/classes/[email protected]#enum-globalscope-error. Modifying @Bromeon The problem with muting this error is that it is also emitted when trying to do any other operation after EOF. So I think we could do something like that: // Error handling utility function.
fn check_error(&self, allow_eof: bool) -> Result<(), IoError> {
let error = self.fa.get_error();
if error == Error::OK || (allow_eof && error == Error::ERR_FILE_EOF) {
return Ok(());
}
Err(IoError::new(
ErrorKind::Other,
format!("GodotError: {}", error),
))
} And passing |
Damn, there is a warning in if (read < p_length) {
WARN_PRINT("Reading less data than requested");
} If we should assume that EOF is always an error, then we have to cache file length :( |
@StatisMike Sounds good. What do you think about covering the different scenarios with one test case each? @andreymal Maybe we should also ask about this in godotengine/godot#85921? It's a bit strange to me that unlike most other file APIs, you can't just "read until EOF" but need to know the file length in advance. |
Ok, so coming back with results.
I'm personally happy with results (especially the
Currently there are test cases for basic EDIT: I think that I could also add |
f6741ce
to
4ef2c28
Compare
Thanks for adding |
4ef2c28
to
5c16d13
Compare
@Bromeon Also added |
Maybe related to this, we have an internal buffer in How do the two play together? |
Internal buffer for Edit: If you don't find any other issues with this I think it could be merged. The BufWriter being marginally slower than |
Regarding EOF, I accidentally started whining in godotengine/godot-docs#8590 but don't know what's next |
@andreymal thanks for your input in this PR! |
Thanks a lot to both of you! |
FileAccess::get_buffer()
andFileAccess::store_buffer()
forRead::read()
andWrite::write()
.BufRead::fill_buf()
.Debug
derive toNotUniqueError
Adresses #513