enwi / dartzmq

A simple dart zeromq implementation/wrapper around the libzmq C++ library
https://pub.dev/documentation/dartzmq/latest/
MIT License
26 stars 17 forks source link

ZeroMQ seems to "wait" one second before receiving data. #4

Open Eerey opened 2 years ago

Eerey commented 2 years ago

Hello there,

I'm testing this feature on windows. When using a push/pull or pub/sub pattern there seems to be a one second delay on the pull/sub socket. Is it built into ZeroMQ or can i configure this behaviour?

Best regards

Eerey commented 2 years ago

Oh, i see, it is here:

zeromq.dart

  /// Starts the periodic polling task if it was not started already and
  /// if there are actually listeners on sockets
  void _startPolling() {
    if (_timer == null && _listening.isNotEmpty) {
      _timer = Timer.periodic(const Duration(seconds: 1), (timer) => _poll());
    }
  }

this should be configurable imo. Is there a particular reason to limit it to 1 second? Best regards and thanks for the plugin, I might use it for a project

enwi commented 2 years ago

this should be configurable imo. Is there a particular reason to limit it to 1 second? Best regards and thanks for the plugin, I might use it for a project

No there is no particular reason. I thought 1 second should be enough for most applications, but making it configurable seems to be the best option here.

Since you already invested some time, do you want to open a PR and make it configurable?

Eerey commented 2 years ago

Will take a while but i can look into it :)

enwi commented 2 years ago

On another note, I was thinking about using another thread just for the ZeroMQ poller. Then we could let it wait without delay and have messages coming in at the quickest rate possible. Though I don't know if that is a good idea. https://pub.dev/documentation/threading/latest/

Eerey commented 2 years ago

@enwi that sounds like a great idea. Can this be done with isolates? Do isolates behave the same on every platform?

enwi commented 2 years ago

@Eerey It should be possible to do it with isolates as well. The main difference between isolates and threads being that isolates do not share memory as threads do. https://itnext.io/minimalist-guide-to-isolates-in-dart-flutter-dd5bdee031e

ach-ee commented 2 years ago

I have implemented asynchronous polling on my fork. You can check it out on this PR. The main change is the ZPoller class and the original Timer implementation has been removed from ZContext.

It works similar to other ZeroMQ implementations - the poller runs on another thread (Isolate in this case) and updates the main thread if there is data available. ZSockets are still updated through their Streams as soon as data is available.

It works well on Linux and I will test it out on Windows soon when I get a chance. I'm fairly new to Dart, so let me know if you have any suggestions for improvements.

enwi commented 2 years ago

Great job on using an isolate to solve this issue @ach-ee ๐Ÿ‘ Could you open a PR?

Also what is you opinion on this https://dart.dev/guides/libraries/create-library-packages#organizing-a-library-package?

enwi commented 2 years ago

@ach-ee Do you have any updates on your changes regarding opening a new PR?

rbebb commented 2 years ago

@ach-ee I would also like to know if there are any updates on opening a PR for this! I also noticed you made a few other changes in your fork that would be great to include in this library๐Ÿ‘๐Ÿผ

stevenlayne12 commented 1 year ago

Hey @enwi, is there a short term fix I can do on my end? I tried using @ach-ee fork but I am afraid getting all this to work is above my paygrade as a flutter novice.

enwi commented 1 year ago

Hey @stevenlayne12 sure there is some kind of workaround by changing the polling interval. Though this could lead to performance issues on some phones, but I am not sure.

Just change the interval here: https://github.com/enwi/dartzmq/blob/26157a6d32412d68c6a89daa9ab0d268fa6b9003/lib/src/zeromq.dart#L68

stevenlayne12 commented 1 year ago

Okay awesome thanks @enwi !

As a separate point, I am trying to achieve low latency communication between flutter and python on linux (and optionally windows just for testing) and landed on using the PAIR socket type because I am looking for low latency bidirectional communication between those two stacks. Does this sound like the way to go? I only ask because I am not sure if this polling issue is partly due to the choice of socket in my case or not

Nevertheless, I will give your suggestion a go! ๐Ÿ‘

enwi commented 1 year ago

@stevenlayne12 the polling approach is currently not the best way to go @ach-ee started working on letting the ZeroMQ code run in another thread, which would be a lot better and have less latency, but I guess he stopped working on that. The code is still available on his GitHub though if you want to have a look.

enwi commented 1 year ago

@canders-rf you can take a look at what @ach-ee did, which is currently in an unfinished state, but essentially the polling loop should be moved into a separate thread so that it can poll with blocking instead of right now where it would hang the whole app.

DonggeonKim1012 commented 1 year ago

Hi @enwi , I know you've been asked about this too many times, but I could really use some help. I'm trying to implement a simple dart req client - python rep server pattern. I've encountered the error 'Operation cannot be accomplished in current state' like many others.

What I'm curious is:

  1. You've mentioned above that the short fix is changing the interval of the polling, but to how many seconds?
  2. ach-ee's fix seems finished. His 'poller.dart' includes the ZPoller wrapper, the _poll function which runs on isolates, and the _pollListener function which connects the main thread's ReceivePort to the isolate. However it still doesn't eliminate the error above, maybe there's something more to be done. I wonder what's your opinion on this?

Really admire the work you're doing. Thanks in advance.

enwi commented 1 year ago
1. You've mentioned above that the short fix is changing the interval of the polling, but to how many seconds?

Less than 1 second, maybe half of that or even 200 or 100 ms.

2. ach-ee's fix seems finished. His 'poller.dart' includes the ZPoller wrapper, the _poll function which runs on isolates, and the _pollListener function which connects the main thread's ReceivePort to the isolate. However it still doesn't eliminate the error above, maybe there's something more to be done. I wonder what's your opinion on this?

It is unfinished, because the main thread is not communicating with the receiving thread if recall correctly