Git Product home page Git Product logo

Comments (11)

cheatfate avatar cheatfate commented on May 25, 2024

First of all current dispatcher even if called global not actually global for process, it is thread global, so it already thread-safe.

What is undefined init order?

And what is better control over which dispatcher is used and when? What is use-case to run two dispatchers in one thread, i dont think you will find any examples of such usage in real world.

The biggest problem here not a constructor API (what does it mean actually?), the biggest problem is Future[T] api which requires access to dispatcher.

from nim-chronos.

arnetheduck avatar arnetheduck commented on May 25, 2024

So the idea here is to rewrite the code so that it can be used without the thread-local.

once you have that, you can start experimenting with multithreaded dispatchers, or dispatchers that have a lock-free queues/channels to take jobs from other threads - you can share a dispatcher between many threads or use one per thread- the key point is is that you leave this choice to the user of the library instead of deciding for them. you gain flexibility and open up future use cases.

you also gain performance on the platforms where the thread-local is slow / emulated. even on "fast" platforms, accessing it has a an indirection cost, as well as an optimization cost (no longer side-effect free meaning compiler cannot reason about it)

also, nothing prevents the thread-local api to be offered on the side - removing accesses to the thread-local gives you a strict super-set of functionality.

from nim-chronos.

zah avatar zah commented on May 25, 2024

FWIW, I had this suggestion in the past, but @cheatfate convinced me that it's not needed.

The main problem is that the Future objects will have to become associated with a particular Dispatcher (by gaining a field). And the main benefit is indeed that we'll be able to consider processing the I/O completions in multiple threads. @cheatfate's argument is that the multi-threading gains can be realized with a different architecture where the socket handle is shared between multiple dispatchers allowing them to accept incoming connections on the same port. I must agree that the multi-threading story in Nim is creating many other obstacles for work-stealing approaches and this solution simplifies things.

Otherwise, the number of times the thread-local variable is dereferenced as such or used as parameter can be tweaked for sure, but this doesn't change the big picture.

from nim-chronos.

arnetheduck avatar arnetheduck commented on May 25, 2024

there's one more use case for this, and that's when you want to integrate with a different event loop, such as the one found in a typical gui framework - this is what I've used the separate dispatchers (io_service) in asio for before - to have different services for different workload "kinds" where for instance I might rely more on buffering for the socket part while async file io gets it's own dispatcher where I poll instead of wait.

for the future issue, intuitively it seems that whatever produced the future already has a dispatcher referenced and will "know" - then one can either track the future in the dispatcher or track the dispatcher in the future. compared to other costs in the system, this seems low - it would be interesting to benchmark so that it doesn't turn out to be a false premise that adding this is a real cost.

also, futures generally can be split into two parts - one for the producer and one for the consumer - you can think of them as little minichannels - special cases of length-1 queues. this tends to allow for some flexibility in where the entities live, and you get to encode a minimal connection between producer and consumer that's very flexible. It's a design I'd need to revisit before describing more fully though, but it's pretty neat for producer-consumer type scenarios.

for the socket case - receives in particular, a future is not really that great an abstraction given that you need to recreate the exact same future every time you read - a subscription tends to be more of what your after where you imagine a stream of data coming through as long as the socket is open - the future is structurally a bad option because you need to pay a separate price for every packet that arrives - that's a much bigger performance cost than adding a field to the future would ever be, in a structurally sound solution.

from nim-chronos.

arnetheduck avatar arnetheduck commented on May 25, 2024

In the same sweep, one would refactor away callSoonHolder which looks dubious, from a design pov - the semantics of setCallSoonProc are pretty unclear and it's easy to mess it up

from nim-chronos.

cheatfate avatar cheatfate commented on May 25, 2024

One of the biggest problems here is Future[T] initialization, to remove dependency on global dispatcher Future[T] needs to hold reference to dispatcher, but this will require {.async.} procedures to have dispatcher as argument. So all the async procedures will require dispatcher as argument.

from nim-chronos.

arnetheduck avatar arnetheduck commented on May 25, 2024

they'll need a dispatcher or an object attached to a dispatcher.. ie if a socket is tied to a dispatcher (which makes sense - you don't want the same socket on two dispatchers), you pass the socket and that's enough..

Putting them explicitly in the API will also allow you to discover hidden dependencies better so that they can be understood without having to scan the whole code - this helps build intuition for how AD works, in general - for example, how the queue works etc..

and like mentioned, there can still be a convenience api that maintains the old global-based ABI

from nim-chronos.

cheatfate avatar cheatfate commented on May 25, 2024

@arnetheduck i understand idea, but i can't figure out how to implement it.

from nim-chronos.

cheatfate avatar cheatfate commented on May 25, 2024

Also you need to consider that usage of more then one dispatcher in one thread is nonsense.

from nim-chronos.

arnetheduck avatar arnetheduck commented on May 25, 2024

btw, can't {.async.} inject the dispatcher automatically in many cases?

one place where it's common to want multiple or separate dispatcher instances is testing: ie you want to create a dispatcher per test to ensure that each test starts with a fresh dispatcher and doesn't affect other tests / is properly cleaned up - it can be solved with a "cleanup" but that cleanup is often buggy itself - much easier to isolate completely with a new instance

from nim-chronos.

cheatfate avatar cheatfate commented on May 25, 2024

@arnetheduck right now {.async.} almost not modifying original procedure declaration, so all the type system works properly and shows proper places for some wrong types, but as soon as we will modify procedure declaration implicitly - all the error messages will be totally broken.

from nim-chronos.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.