fastwebsockets icon indicating copy to clipboard operation
fastwebsockets copied to clipboard

poll_* methods to support custom futures implementations

Open dgrr opened this issue 1 year ago • 19 comments

dgrr avatar May 29 '24 15:05 dgrr

I'll implement the poll_* methods for the WebSocketRead & WebSocketWrite

dgrr avatar May 29 '24 15:05 dgrr

btw, if you implement Stream + Sink from futures you can call split. It's difficult for Stream to return a Frame<'_>, or maybe impossible

dgrr avatar May 29 '24 20:05 dgrr

Would love to see this land. This library would become a great alternative to tokio-tungstenite and tokio-websockets in that case. Especially since it supports true, lock-free stream splitting.

matheus23 avatar Jun 20 '24 09:06 matheus23

FWIW, it'd be nice to have the same poll_ treatment for FragmentCollectorRead :eyes: :grin:

matheus23 avatar Jun 20 '24 12:06 matheus23

btw, if you implement Stream + Sink from futures you can call split. It's difficult for Stream to return a Frame<'_>, or maybe impossible

This is true, but internally it means it'll simply create two references to the same thing using a BiLock. So you end up locking every time you use either the Stream or Sink.

Having a "true" split implementation that is lock free would be a lot cooler! :)


Also, while it's impossible to write an implementation of Stream<Item = Frame<'???>>, it's possible to map the Frame<'f> into your own domain-specific application struct that doesn't have a lifetime, e.g. by parsing binary and text frames into your own types, before returning them in your stream implementation as Items.

Just spelling this out for anyone reading this :v:

matheus23 avatar Jun 24 '24 06:06 matheus23

Having a "true" split implementation that is lock free would be a lot cooler! :)

How is this not lock free? If you use tokio::io::split it will use a Mutex internally.

Also, while it's impossible to write an implementation of Stream<Item = Frame<'???>>, it's possible to map the Frame<'f> into your own domain-specific application struct that doesn't have a lifetime, e.g. by parsing binary and text frames into your own types, before returning them in your stream implementation as Items.

Yes, that's what I do mostly. Because I want my code to be compatible with futures::Stream and Sink. I shouldn't but I had to code it in a bit of a rush 👀

dgrr avatar Jun 24 '24 06:06 dgrr

Having a "true" split implementation that is lock free would be a lot cooler! :)

How is this not lock free? If you use tokio::io::split it will use a Mutex internally.

Yeah no I'm agreeing with you and that's exactly what I'm trying to say. You wrote "if you implement Stream + Sink from futures you can call split.", but that gives you worse performance than having the stream and sink already split from the start :v: (which this PR enables/makes easier!)

matheus23 avatar Jun 24 '24 07:06 matheus23

Yeah no I'm agreeing with you and that's exactly what I'm trying to say. You wrote "if you implement Stream + Sink from futures you can call split.", but that gives you worse performance than having the stream and sink already split from the start ✌️ (which this PR enables/makes easier!)

Ah yes, but it is mainly for compatibility because sometimes it might be useful to use futures::StreamExt. Anyways, the user can implement it on their own, given that Frame<'_> cannot be returned as the Item in futures::Stream

dgrr avatar Jun 24 '24 07:06 dgrr

@matheus23 about poll in FragmentCollectorRead, what would you expect? Do you expect a callback also or that it returns early with the mandatory reply frame?

dgrr avatar Jun 24 '24 14:06 dgrr

Personally, I'd highly prefer returning the mandatory frame :)

matheus23 avatar Jun 24 '24 15:06 matheus23

Personally, I'd highly prefer returning the mandatory frame :)

Indeed. Me too

dgrr avatar Jun 24 '24 17:06 dgrr

Just as an FYI, I've been trying to get the benchmarks to compile & run here on my NixOS to help diagnose the regression, but I'm still fighting my way through with the linker. Will of course post once I got something.

matheus23 avatar Jun 30 '24 18:06 matheus23

Just as an FYI, I've been trying to get the benchmarks to compile & run here on my NixOS to help diagnose the regression, but I'm still fighting my way through with the linker. Will of course post once I got something.

I managed to reproduce the benchmarks, not in macos in Linux, but I cannot find where the regression is

dgrr avatar Jun 30 '24 19:06 dgrr

Further testing shows that, for large buffers, removing the vectored write support is a significant source of the regressions. Now the difference it just 43500 Msg/sec compared to 44000 Msg/sec

Opened a PR against this PR 😅 https://github.com/dgrr/fastwebsockets/pull/1

conradludgate avatar Jul 01 '24 08:07 conradludgate

@littledivy it seems that this PR is ok now thanks to the contributions of @conradludgate

dgrr avatar Jul 06 '24 22:07 dgrr

@littledivy All checks have passed successfully 🚀. Could you please review and merge this PR at your convenience 🙏.

Thank you @dgrr and @conradludgate for your kind contributions in making this library even better. 🫡

ShabbirHasan1 avatar Jul 29 '24 07:07 ShabbirHasan1

@littledivy

dgrr avatar Sep 01 '24 13:09 dgrr

Any chance this will be merged soon?

spy16 avatar Jul 02 '25 05:07 spy16

Any chance this will be merged soon?

@spy16 I gave up, just use yawc

dgrr avatar Jul 02 '25 07:07 dgrr