-
Notifications
You must be signed in to change notification settings - Fork 224
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
Reimplement slurp
with os/open
.
#1397
Comments
Here is a bigger question: how much OS function support should Janet have when compiled without event loop? |
I don't know. |
This might be something better with spork. Linux, and I suspect other operating systems, make reading and writing from the file essential synchronous. A re-implementation of slurp that uses |
is current
|
You mean |
Sort of. I was wonder because @bakpakin said
|
Even if you use poll or select on files in Linux, reading and writing can still block. Yes, for special files and pipes this might fix a problem but I think it makes more sense to just move to spork. |
What do you mean? Do you mean that |
I don't know what to add to spork because I don't have grasp of the problem. |
What I was trying to say is that the implementation is straight forward, but that it is not all that valuable. For more information, here is a mailing list that in short describes the issue: https://utcc.utoronto.ca/~cks/space/blog/linux/HardAsyncFileIO If you show some motivating code where blocking the event loop was an issue, maybe we could offer more help. |
io_uring would not block for data read on Linux; |
An io_uring event loop would be nice and probably work, but again for such a high performance requirement, the other abstractions in Janet would likely be unsuitable anyway. Not to mention a requirement on more modern kernel versions. |
If you raise minimum required kernel version, you can implement asynchronous file IO now? |
It would look like aio(7) - See notes section. |
In case things change, here are some bits from the linked page:
|
Thinking through this... let's say it was implemented with Would the idea of re-implementing (while (ev/read file 4096 buf)
(ev/sleep 0)) |
But what if you build Janet without |
I'm unsure if Janet-side code has the ability to detect if |
There is this section in /* These settings should be specified before amalgamation is
* built. Any build with these set should be considered non-standard, and
* certain Janet libraries should be expected not to work. */
// ... elided ... //
/* #define JANET_NO_EV */ |
Regarding detection of |
It seems superfluous. TBH, the whole debate is just bikesheding to me. Even the name |
I don't really understand your comment. Would you mind elaborating on it? |
I meant that I see But most of all, looking at the length of this thread, it is not worth the cause. |
Thanks for the explanation. |
FWIW, I'm not convinced that the idea mentioned by llmII was not worth continuing to discuss. It seemed a bit premature to stop the conversation. |
I want to know what can replace
Does this yield to the event loop regularly? If IO itself was synchronous, I would still want to yield to the event loop after reading a chunk of 4 kilobytes or something like that. In real code, I would probably use
or
I think |
@amano-kenji Please note that The following example code illustrates this working for anyone who comes back to look at this issue in the future, and outlines how Before we begin we should note that for the event loop to be able to schedule something other than the currently running fiber, the currently running fiber must yield to the event loop. It may not seem intuitive but You'll need to modify the example to use a suitably large file, and change what the file is that it's opening. If you're on *nix something like Example: (def buf @"")
(def tf (ev/spawn
(protect
(forever
(ev/sleep .5)
(print "Here we are @" (length buf))))
(print "Last @" (length buf))))
# optionally use `os/open`, makes no difference
(with [f (file/open "/tmp/bad-file" :r)]
(while (:read f 4096 buf)
(ev/sleep 0)))
(print "We read 1gb!")
(ev/cancel tf :cancel) Example output:
Example slurp implementation that won't block tasks as badly as reading all the bytes in one go: (defn slurp
``Read all data from a file with name `path` and then close the file.``
[path]
(def buf @"")
# optionally use `os/open`, makes no difference
(with [f (file/open path :rb)]
(while (:read f 4096 buf)
(ev/sleep 0)))
buf) |
Closing this as the solution posted here should work as expected. |
Right now, it uses
file/open
.file/
functions block the event loop.os/open
creates a stream which doesn't block the event loop.The text was updated successfully, but these errors were encountered: