-
Notifications
You must be signed in to change notification settings - Fork 26
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
Poor performance? #50
Comments
This is likely because the methods for vector streams always operate element-by-element: Lines 235 to 252 in 74a1027
Lines 262 to 270 in 74a1027
It should be possible to optimize these with techniques like |
@phoe that's clearly one case that can be optimized. But |
Good catch - in that case, it might be generic dispatch overhead, since each byte means a single GF call. Are you required to use |
But in any case, I'm doing a lot of |
Profile this maybe? We'll see where most of the time is spent this way. |
Hmm.. just a quick
So yeah, I thought that transformers might be a big issue.. Is there anyone actually using this feature? |
With the current behavior, This still won't fix the problem of needing to call it every time if you end up using |
Perhaps a better way would be to have separate stream classes that support transformers? It's a pity that an optional functionality that not everyone needs slows down basic operations for everyone.. For my particular case I'll probably ditch streams completely, and cook my own helpers to work with a binary sequence (adjustable, for output). But I suspect a lot of projects would benefit from improving |
I think I'll rest my case here, which unfortunately is bad news.. I wrote my own memory stream. It's the simplest, dumbest code possible, and it is significantly faster than flexi in-memory vector streams (write time: 1.660s vs 2.136s, read time: 2.253s vs 3.506s), but it's still nowhere near native stream performance (which even does actual I/O). Kinda defeats the purpose of using a memory stream. I guess the sad, inescapable conclusion is that the slowness is inherent in the Gray Streams protocol itself (as @phoe suspected, generic dispatch overhead). |
@mishoo, is this test really informative in a useful way? Performance of some operation, like stream input or output, makes sense when compared with surrounding computation, or data processing. "What fraction of my application performance is spent in stream writing?" would be a more useful question, IMHO. In this test there is nothing except invocations of the io functions. The single byte, or a small array, by reference, is passed through a series of function calls, and finally copied. Even in the function call frames this byte constitutes a marginal part. It's like creating a dummy empty function with
What is the purpose of a memory stream? If you mean some buffering, then the streams SBCL creates with If native streams were unbuffered, with every IO operation resulting in a system call and physical storage device access (kernel disc cache disabled), then accumulating data in a memory stream first would result in a huge speedup, I believe. |
@avodonosov Story time :) In short, I'm working on a binary encoding to replace JSON. I believe JSON is overkill for data interchange between programs — think about how much time is spent encoding it on one side, and decoding it on the other. I'm just testing out ideas. I think I have some pretty good ones. But if I want the world to consider reading beyond the title of my spec, I need to prove that it is indeed faster than JSON libraries such as jsown. In trying to do that, I concluded that it's Simply Just Not Possible™ to even come close to its performance using any kind of stream layered on top of |
Is extending simple-streams (assuming you're OK with SBCL) an option for you?
On Saturday, October 14, 2023 at 04:01:07 PM GMT+8, Mihai Bazon ***@***.***> wrote:
@avodonosov Story time :) In short, I'm working on a binary encoding to replace JSON. I believe JSON is overkill for data interchange between programs — think about how much time is spent encoding it on one side, and decoding it on the other.
I'm just testing out ideas. I think I have some pretty good ones. But if I want the world to consider reading beyond the title of my spec, I need to prove that it is indeed faster than JSON libraries such as jsown. In trying to do that, I concluded that it's Simply Just Not Possible™ to even come close to its performance using any kind of stream layered on top of trivial-gray-streams for reading data from memory (and many times the payload will already be in memory), so I had to roll my own functions for reading from/writing to an in-memory sequence of bytes. The end.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you are subscribed to this thread.Message ID: ***@***.***>
|
@Symbolics yeah, SBCL is what I use, but I don't know about simple-streams. For now I'm happy with what I got — I won't be able to read/write directly using a Lisp stream, but it is already better than JSOWN. I only filed this here because I initially thought FLEXI-STREAMS is the culprit for the slowness. I still believe it can be improved (e.g. by getting rid of the transformer), but a big part of it is due to dynamic dispatch, and that can't be fixed. :-\ Dunno, feel free to close the issue if you think it isn't worth the trouble. BTW, this project isn't about Lisp. I hope this (or some similar) binary encoding becomes as ubiquitous as JSON, because we really need one. It just happens that CL is the language I like most to work with, so I'm writing my reference encoder/decoder in it; but I should write one in JS too, if I want anyone to take this seriously. :) Hope to publish something soon. |
@mishoo, if jsown does not read from / to stream, probably doing it in your library wouldn't be a fair comparison. BTW, I noticed generic functions are used in jsown code, it's not free from generic functions. You of course know about MessagePack, protobufs, BSON and everything else ? Anyways, good luck with your approach. |
An idea for how to use stream functions as the lowest common denominator for data access in a library, and still be fast. If anyone knows a more performant dispatch approach than the Gray Streams prototocl, he could create his own package, say By default those functions would delegate all work to their counterparts from the But also those functions could use the more performant dispatch for pluggable stream implementation, to invoke custom implementation if called with new custom stream. That way, the code that performs all IO using the And such a package could be a drop-in replacement for the standard cl stream functions, just use shadowing-import-from in the application package definition to employ them. The only doubt: if people will repeat this trick many times, producing more and more packages like |
Indeed,
I only learned about CBOR yesterday :)) Looks like I've been living under a rock. It renders my efforts pretty moot, since CBOR is a standard. Still, it was fun, I learned things :) and my encoding might not be entirely without merit so I'll get to publish it eventually. Obligatory XKCD :) https://xkcd.com/927/ Back to the original issue, I also noticed this years ago (my site is served by Hunchentoot). I can't unlearn the fact that it could be improved like 4x… I'll try it myself sometime. |
Hi folks,
I'm working on a toy project that involves encoding/decoding some binary data, and I happened to notice that using flexi-streams' in-memory streams is much much slower vs. reading/writing from a binary file. Just wondering if there is any reason for this weirdness. Here is a simple test function (it'll output like 50M into a file in
/tmp/
).Results here look like this:
I'm using SBCL 2.3.9.63-23c796775.
I'm not sure something can be done about it, but if it's possible to improve, I guess a lot of projects will benefit. In my case I'm forced to ditch flexi-streams for now; the difference is so big that if I have the data in memory, I'm better off dumping it into a file and read it back from there, rather than going through
in-memory-input-stream
.The text was updated successfully, but these errors were encountered: