Comments (11)
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.
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.
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.
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.
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.
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.
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.
@arnetheduck i understand idea, but i can't figure out how to implement it.
from nim-chronos.
Also you need to consider that usage of more then one dispatcher in one thread is nonsense.
from nim-chronos.
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.
@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)
- compiler error on simple async proc HOT 1
- asyncloop `isCounterLeaked` returns incorrect value?
- chronos is not available in Nim Playground? HOT 2
- httpclient: The content of HostHeader is incorrect when redirecting to a different host HOT 1
- Write to `Future.internalValue` directly in macro-translated code
- `getAcceptInfo` can raise an unlisted exception: ref ValueError HOT 2
- Apparent garbage collect of localCopy in datagram sendTo before data gets send in writeDatagramLoop HOT 2
- Cycle-based memory Leak under --mm:arc HOT 1
- chronos/threadsync errors when compiling documentation
- bug: TokenBucket update calculates wrong with lastUpdate timestamp HOT 1
- Reading a file asynchronously? HOT 1
- Async proc: both Option[seq[T]] and Opt[seq[T]] as return type and one of the params is generic, failed to compile with Nim-devel HOT 1
- Completing `Futures` in refc may have unexpected behavior HOT 1
- `cancelAndWait` on `or` triggers deadlock
- `SIGSEGV` in `asyncTest`-derived scenario (also, in `asyncTest`) HOT 5
- Can't compile on GCC 14
- ambiguous identifier: `'Result'` HOT 2
- Change header size limits HOT 2
- Its impossible to specify Future[T].Raising([]) as argument.
- What is the intended method for catching exceptions raised from asyncCheck'd Futures? HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from nim-chronos.