Skip to content
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

It is necessary to implement threads #333

Open
insinfo opened this issue Apr 27, 2019 · 184 comments
Open

It is necessary to implement threads #333

insinfo opened this issue Apr 27, 2019 · 184 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@insinfo
Copy link

insinfo commented Apr 27, 2019

It is necessary to implement threads, because in the majority of platforms that run Dart supports thread, such as Android, iOS, Windows, Linux, MacOS, * WebAssembly etc.

Many use cases where thread can be used easily and quickly to speed up the processing of tasks.
I use enough threads in Java Android / Linux and C #.

Threads can communicate with each other more easily than processes.

Isolated objects do not share compiled code or JavaScript objects and therefore can not share changeable data as pthreads.

Although the Isolate can provide concurrent programming behavior, it does not have the advantages of the threads, because with the threads there is shared memory and with the Isolate there is not. There are many advantages to threads over multiple processes such as lower memory consumption, another advantage of using a thread-based model is that it is fast, threads are lighter than Processes.
Another disadvantage of using a process-based model is that it will be slower. You will have to copy data between the competing parts of your program.

This does not mean that you have to abandon the Isolated Processes, but instead add another option to the most common cases where you want to accelerate an algorithm that can be easily and quickly paralleled with Threads

  • It would be nice if Dart already had an AOT compiler or a VM for WebAssembly
  • WebAssembly threads ready to experiment
@lrhn
Copy link
Member

lrhn commented Apr 29, 2019

The primary disadvantage of shared-memory concurrency is that you need to maintain a consistent memory across threads, avoid concurrent modifications and access to uninitialized or partially modified objects and provide concurrent allocation.

A secondary issue is that concurrency is not supported when compiling to JavaScript.

It would be nice to have some version of concurrency that is easier to use than isolates, even if it's only shared access to immutable memory or explicitly opt-in shareable memory. That's still a tough restriction for a language like Dart which has globally accessible mutable variables.

@MarvinHannott
Copy link

@lrhn

A secondary issue is that concurrency is not supported when compiling to JavaScript.

But isn't that what service workers should be capable of?

@ramsestom
Copy link

ramsestom commented Nov 20, 2019

I can't agree more with @insinfo .
I think the reason why threads where not implemented into Dart in the first place is because Dart was mainly focused into compiling to JavaScript (that don't support threads natively). But things have changed and now, most of the developpers are focusing the dartvm (via Flutter or directly) so the lack of proper thread support in Dart has really became an issue. As a developper, working with Isolates is not only painful, it is also highly ineffective when you have to copy (serialise/deserialise) a large collection of complex objects between isolates (for example if you have to perform a filtering/computation on a large collection of objects into an Isolate).
So I think that having a proper support of threads in Dart should be a priority of the dart-lang team as, unfortunately, unlike other features currently missing in Dart (enums with value storage, protected variables and methods visibility...) there is no alternative that we can develop, as a developer, to replace this lack of support of threads in Dart (Isolates are probably one of the things Flutter developpers are struggling the most with).

@lrhn

The primary disadvantage of shared-memory concurrency is that you need to maintain a consistent memory across threads, avoid concurrent modifications and access to uninitialized or partially modified objects and provide concurrent allocation.

This is the case for all languages supporting threads (=pretty much all modern languages) so it shouldn't be that much of an issue. Anyway all devices are now multicores so offering the possibility to share memory between process seems essential for any language turned to be still usefull and used in the future.

A secondary issue is that concurrency is not supported when compiling to JavaScript.

To support threads into dartjs, you should probably take an approach similar to the one took by the TeaVM team to compile Java bytecode to JavaScript. They fully support the conversion of Java (and Kotlin and Scala and any language that can compile into bytecode to the JVM) Threads into Javascript by transforming them into green threads (http://teavm.org/docs/intro/overview.html)

I really hope that Dart will offer a full support of threads soon (for dartvm first, it can come to dartjs latter) as this is a feature that is essential to really develop powerfull apps.

@MarvinHannott
Copy link

@ramsestom

As a developper, working with Isolates is not only painful, it is also highly ineffective when you have to copy (serialise/deserialise) a large collection of complex objects between isolates (for example if you have to perform a filtering/computation on a large collection of objects into an Isolate).

Most of the time copying is really really cheap compared to the actual computation and shared memory isn't worth the headache. Also don't think thread synchronization comes for free! In fact, copying might not be any slower. There is also TransferableTypedData to move TypedData from one Isolate to another. Of course that isn't true for any other data structure since there is no copy constructor, so the Dart runtime wouldn't know how to properly copy a class instance (at least if it isn't a constant).

But if you truly need shared memory then you could use a pointer from dart:ffi. This might be a dirty trick but it absolutely works and you only have to copy the pointer address. Naturally it brings back all the problems with synchronization and you have to free the pointer manually. And in most cases it won't increase performance at all (rather the opposite).

The design of Isolates isn't ineffective at all; in fact from a gc's point of view it is very effective. It also makes other things like certain compiler optimizations and memory management simpler. And it practically erradicates race conditions. Many programming languages like Erlang or Go don't share memory and pass messages, and obvioulsy they do fine. I also don't think the async features of Dart would play nice with thread synchronization. And (native system) threads wouldn't play nice with Dart's Observatory which is a very powerful tool.

I would also be interested why you think working with Isolates is more painful than working with threads in any other language. For all practical purposes Isolates can be viewed as threads. The API i just as "low level" as it has to be to satisfy all use cases. But there are higher level abstractions like the pub package isolate which make dealing with Isolates much easier.

The primary disadvantage of shared-memory concurrency is that you need to maintain a consistent memory across threads, avoid concurrent modifications and access to uninitialized or partially modified objects and provide concurrent allocation.

This is the case for all languages supporting threads (=pretty much all modern languages) so it shouldn't be that much of an issue. Anyway all devices are now multicores so offering the possibility to share memory between process seems essential for any language turned to be still usefull and used in the future.

I would claim this is evidently not true. There are many languages which don't share memory and CSP libraries for C++ and Java are very popular.

@ramsestom
Copy link

ramsestom commented Nov 21, 2019

Most of the time copying is really really cheap compared to the actual computation and shared memory isn't worth the headache. Also don't think thread synchronization comes for free! In fact, copying might not be any slower.

I didn't say that synchronisation comes from free but copying is not cheap. In terms of computation time, it isn't cheap when you have large data to copy (parsing a large json file and returning the result, decoding an image...) and even if the copy time might be much smaller than the computation time taken by the whole Isolate process, copying the data back to the main Isolate (=the IDE if you are on a Flutter app) might take enaugh time to have this IDE Isolate to hang on and be noticed by the end user. And in terms of memory, copying is not cheap at all as you add another copy of your data for each new Isolate. You don't have these issues with Threads that can share memory.

But if you truly need shared memory then you could use a pointer from dart:ffi. This might be a dirty trick but it absolutely works and you only have to copy the pointer address. Naturally it brings back all the problems with synchronization and you have to free the pointer manually. And in most cases it won't increase performance at all (rather the opposite).

Do you have any example on how to use dart:ffi to share pointers between Isolates? I would be interested even if it is a dirty hack. Anyway, if any Isolate can access any data produced by other Isolates given a pointer to this data in memory, it means that Isolates already have shared memory (it is just not synchronised). So having a proper implementation of Threads in Dart would just be a matter of correctly handling synchronized access to data declared as synchronized by the developer. Isn't it? Seems like something the Dart language should offer without having to rely on dirty hacks...

The design of Isolates isn't ineffective at all; in fact from a gc's point of view it is very effective. It also makes other things like certain compiler optimizations and memory management simpler. And it practically erradicates race conditions. Many programming languages like Erlang or Go don't share memory and pass messages, and obvioulsy they do fine. I also don't think the async features of Dart would play nice with thread synchronization. And (native system) threads wouldn't play nice with Dart's Observatory which is a very powerful tool.

Threads doesn't necessarily have to be native. Dart could choose to provide green threads in wich case Threads would work pretty much like Isolates exept that they would offer access to shared memory and ensure synchronised access to part of this memory declared as synchronised. In this case I think that Dart's Observatory would still play nicely with Dart threads. As for the async feature of Dart, languages like Python or Java have shared threads memory but also support async/await or Futures so it shouldn't be an issue.

I would also be interested why you think working with Isolates is more painful than working with threads in any other language. For all practical purposes Isolates can be viewed as threads. The API i just as "low level" as it has to be to satisfy all use cases. But there are higher level abstractions like the pub package isolate which make dealing with Isolates much easier.

When working with Isolates you not only have to create the send/receive ports each time you want two Isolates to be able to communicate but you also have to ensure that each data structure you want to send through the port is serialisable/deserialisable and to write a routine in the sender on how to find and send the data requested by the recever. Things can even turn a lot more complicated if you want to launch a new Isolate from another Isolate and have to broadcast data from one Isolate to another through an intermediate Isolate ports. With threads and shared memory everything is a lot more easier, you can have static synchronized repositories for your data and you would be able to access them from any Thread without the headache of asking the spawning Thread the data or passing throw the whole Thread hierarchy in case of cascade Thread calls.

@MarvinHannott
Copy link

it isn't cheap when you have large data to copy (parsing a large json file and returning the result, decoding an image...) and even if the copy time might be much smaller than the computation time taken by the whole Isolate process, copying the data back to the main Isolate (=the IDE if you are on a Flutter app) might take enaugh time to have this IDE Isolate to hang on and be noticed by the end user.

With TransferableTypedData there should be only one copy. While the child isolate copies the data, the main isolate shouldn't block; after all, ports work asynchronously. In theory the user shouldn't notice anything. If memory is a concern and you parse really really huge data sets then you might want to use C/C++/Rust, either through ffi or native extension. Native extensions can work asynchronously as well. Might worth a look.

Do you have any example on how to use dart:ffi to share pointers between Isolates?

// main isolate
// [allocate] is in package ffi, not dart:ffi
final ptr = ffi.allocate<ffi.Uint8>();
port.send(ptr.address);
...
ffi.free(ptr);

// child isolate
port.listen((int address){
  final ptr = ffi.Pointer.fromAddress(address);
});

This pointer points to shared heap memory not managed by the dart runtime but by the operating system! And allocating memory and copying list elements into it is really slow. This is a pointer you would pass as a parameter to a C function. If you free the pointer while it is used in another isolate it leads to undefined behaviour. If you don't free it it leads to a memory leak. I wouldn't recommend doing this since it isn't more memory efficient or faster. Better use TransferableTypedData or consider going native in the first place.

As for the async feature of Dart, languages like Python or Java have shared threads memory but also support async/await or Futures so it shouldn't be an issue.

But there are issues. Synchronization involves blocking. Python has the famous Global Interpretation Lock (or GIL) so the reference counter works as expected. Nobody uses threading in Python for that reason alone (except with PyPy which indeed uses green threads). And thread synchronization in Java can hurt asynchronicity as it is the direct opposite. So most web developers avoid it. You were worried about UI becoming unresponsive, yet blocking is the reason for that. Isolates have become much more lightweight than they used to be.

When working with Isolates you not only have to create the send/receive ports each time you want two Isolates to be able to communicate

Well, not if you just use the higher level abstractions offered by the Dart team.

you also have to ensure that each data structure you want to send through the port is serialisable/deserialisable

That might indeed be a pain point with nested data structures. But in most cases the data is serializable. As far as I know the Dart team is working on this.

Things can even turn a lot more complicated if you want to launch a new Isolate from another Isolate and have to broadcast data from one Isolate to another through an intermediate Isolate ports.

To be honest, I never encountered that scenario. And I am not entirely sure I can follow. You mean that two or more child isolates spawned by a parent isolate couldn't communicate with each other? I know that a ReceivePort can be transformed into a broadcast stream with many subscribers. I think it should work across isolates.

@GabrielRatener
Copy link

@lrhn About the whole compile to JS thing.

Shared memory multithreading is compatible with JS, because it can compile to single threaded code. It basically won't break anything, it just won't provide any performance benefits on the web.

I don't see why this should be an issue when the web will underperform other Dart runtimes anyhow.

@lrhn
Copy link
Member

lrhn commented Nov 29, 2019

A feature which performs badly can be worse than no feature at all.

The end result is still guidelines saying "don't use X, it's too slow", so will users not get the benefits of feature X. They'll still pay for the extra implementation overhead anyway, and the mental overhead of knowing, and then ignoring, the feature.

Or, in other words, I'd rather do nothing than do something badly.

@insinfo
Copy link
Author

insinfo commented Dec 4, 2019

I believe the future is WebAssembly, because soon WebAssembly will have direct access to the browser WEB APIs and will no longer need to compile for javascript.

@MarvinHannott
Copy link

@lrhn About the whole compile to JS thing.

Shared memory multithreading is compatible with JS, because it can compile to single threaded code. It basically won't break anything, it just won't provide any performance benefits on the web.

I don't see why this should be an issue when the web will underperform other Dart runtimes anyhow.

That indeed would work, but might not be what the developer wants or expects. If responsiveness / time to compute weren't an issue we wouldn't consider parallelism in the first place. So one could also argue that web workers should be used, though they don't use shared memory.

If we really want to keep JavaScript as a compile target we also ought to have similar semantics. Though to be honest, with TypeScript and other better suited solutions out there, I don't see why we should care about this any longer. Outside of AngularDart no one uses Dart as a compile to JavaScript solution, and even AngularDart is rarely used. Just my humble opinion.

@ebesirik
Copy link

you also have to ensure that each data structure you want to send through the port is serialisable/deserialisable

That might indeed be a pain point with nested data structures. But in most cases the data is serializable. As far as I know the Dart team is working on this.

A Huge/Mega/Collosal/Epic "pain point", in some cases I/We have to move mountains to overcome this issues that come with mandatory "serialisable" data.

Besides Java for instance has built in Concurrent versions of mostly used DataTypes. I never had any issues about concurrency in Java even though I heavily used it...

Qt has a similiar mechanism with signals/slots but you can transfer any Type as long as you register it AFAIK. No Limitaions...

Dart IS limiting, enforcing developers to its own way of thinking, instead, it should provide me everything and let me worry about ist downsides or intricasies but do not limit me...

@insinfo
Copy link
Author

insinfo commented Feb 18, 2020

@nomercy78 I agree with you

Dart IS limiting, enforcing developers to its own way of thinking

@MarvinHannott
Copy link

@nomercy78

A Huge/Mega/Collosal/Epic "pain point", in some cases I/We have to move mountains to overcome this issues that come with mandatory "serialisable" data.

Besides Java for instance has built in Concurrent versions of mostly used DataTypes. I never had any issues about concurrency in Java even though I heavily used it...

https://api.dart.dev/stable/2.7.1/dart-isolate/SendPort/send.html

The content of message can be: primitive values (null, num, bool, double, String), instances of SendPort, and lists and maps whose elements are any of these. List and maps are also allowed to be cyclic.

Most dart:collection types can be easily converted to a List or Map. Converting user defined types can be a hassle, but there are libraries for automatic code generation. I don't see how anybody has to "move mountains". Though I would see the point in a sendable interface to abstract the serialization away from the user.

There have been good arguments, why system threads are not part of the platform, although they evidently work fine. That is not the point. If anybody urgently needs threads, he could pull it of by native extension. Shouldn't be too hard either.

@pratikpparikh
Copy link

If dart ever look at implementing thread, they should look at java loom. Some good reading on loom.

@insinfo
Copy link
Author

insinfo commented Jul 9, 2020

the dart team could at least make an extension or a separate opcional package that implements thread

@lrhn
Copy link
Member

lrhn commented Jul 10, 2020

Concurrency is not a feature you can just add with a package.

The Dart design is completely single-threaded, and adding support for concurrency would require adding a memory model that can handle concurrency. That's something which Dart doesn't currently have.

I'd go for having a much more efficient implementation of Isolate instead. An Isolate.spawn() operation should be able to be quite efficient.

@pratikpparikh
Copy link

the dart team could at least make an extension or a separate opcional package that implements thread

@insinfo I found the following package https://pub.dev/packages/threading.

@maxim-saplin
Copy link

maxim-saplin commented Mar 28, 2021

Thumbs up for better parralelization options with Dart since the Isolate model is indeed limmiting and does not provide efficient and effective ways to benefit from multi-core CPUs.

It is a trend of the recent 15 years in processor development where increased parallelism (number of cores) is the primary driver of performance growth. A typical smartphone now has 8-core CPU, AMD and Intel offer consumer products with 16 cores. Imagine a single threaded Dart program in 2025 running on a mid-range smartphone using one core out 16 available... Technically there're multiple helper threads in Dart, such as running GC, thoug they are not available to devs and don't help with code parallelism.

Few remarks to the above posts:

  1. People say data get's copied when transfered between isolates. It's not completely true. As long as we don't deal with raw bytes (such as TypedData collections), data gets serialized/deserilized on both ends and it is not as fast as simple byte copy. Even string converstions via Utf8.encode/decode (epsecially if we have non-ASCII strings) can present significant overhead. 99% of their time developers deal with object graphs, not raw bytes, and marshaling those objects between isolates is way more expensive than sharing memory.

  2. Indeed modern hardware makes it possible to ignore the overheads associated with certain programming paradigms, such as parallelism with isolates in Dart (or data immutability in Redux) - extra CPU cycles or bytes of memory won't be noticed in typical use cases. Though I can imaging a few scenarious (actualy real ones I faced with Flutter) where Dart's Isolates can be a dead-end or make devs doing complicated workarounds:

    2.1. In a Flutter app where we want to target 120FPS no single frame (or item from the message queue) can run for more than 8ms. One of clicks in the app triggers an HTTP request, which returns JSON and desrializes it to a list of Dart objects. Just like Flutter docs recommend we use Compute() function to create an isolate, make there an HTTP request, run JSON deserialization and return the result to the main isolate. If JSON happens to contain hundreds of thousands of objects, receiving the list (of Dart objects already deserialized from JSON in the secondary isolate) on the main isolate can easily take tens and hundreds of milliseconds and Flutter's promised high FPS are not achievable in this scenario.

    2.2. If one needs to iterate through a large list of objects and aggregate some value (e.g. compute sum on a few fields), using threads and shared memory can give nearly X times performance boost (where X is the number of cores/threads available). With isolates there're barely any options to efficiently utilize multiple cores. E.g. in .NET there's TPL (Task Parallel Library) which aims to help with that kind of cases via Tasks (which are C# alternative to Futures) running in a thread pool.

  3. Apparently with Dart there's a tradeoff, you either simplify the async/await/concurency model and make it easier to create simple and stable code OR you deal with threads and all the evils associated (mutexes, critical sections, deadlocks and race conditions etc.). And you either have the language easily transpiled to JS (which is single threaded) or you don't target Web.

    3.1. It seems WASM threads are coming to browsers (https://github.com/WebAssembly/threads) and there're requests to add threads to WASM thread implementation to Mono (Add mono.wasm support for threads mono/mono#12453) and Microsoft's Blazor framework (runninig on top of Mono).

@johannphilippe
Copy link

I want to see native threads in Dart.
Isolates are very limitating in Dart, espacially since the language is stable for desktop platforms.

There are many reasons why we would want to see native threads :

  • Data sharing between threads in critital operations - where copy or serialize/deserialize can be too slow
  • Ease of writing - I personnaly find it easier / faster to write critical sections with threads than with Isolates. This is because with threads I only have to take care of sensitive data (mutex and locks where read/write operations can be done at the same time by two threads). Isolates makes you write a lot of code, since you have to create a message / port type for each data you want to share, even if it's not critical data.
  • Since it is more permissive, threads allow programmer to be more powerful, that's what we expect from a programming language.
  • ....

Of course, that would probably imply to modify or to adapt memory model of Dart. But AFAIK it seems necessary if Dart wants to conquest desktop application world. That would be the best improvement to the language right now.
People who want safe concurrency model could then use Isolates. But for a lot of specific applications, we need those old unsafe threads.

@lrhn lrhn added the feature Proposed language feature that solves one or more problems label Apr 23, 2021
@insinfo
Copy link
Author

insinfo commented Aug 2, 2021

@johannphilippe
I fully agree

where copy or serialize/deserialize can be too slow

@johannphilippe
Copy link

johannphilippe commented Aug 3, 2021

I'm actually thinking about something probably more fitted to Dart : a SharedMemory class that could be accessed from different isolates :

  • No GC (user responsibility to free this shared memory)
  • Isolates locks
  • Could be shaped like a Map (String keys to access memory blocs)

For example :

SharedMemory mem = SharedMemory();
mem.allocate(String blocName, int numBytes);
mem.lock(String blockName);
mem.unLock(String blocName);
mem.write(String blocName, dynamic data, {int indexOffset = 0});
mem.read(String blocName, int indexOffset, int sizeOfData);
mem.free(String blocName);

That is only a prototype, but such a class could solve a big part of the problem here.
I don't even know if that would be possible to create such a class on the user side, since Isolates are so... isolated.

And still, native threads would be better to me.

@mraleph
Copy link
Member

mraleph commented Aug 3, 2021

I don't even know if that would be possible to create such a class on the user side, since Isolates are so... isolated.

You can relatively trivially create such class using dart:ffi (or in general: you can easily share data between isolates as long as it lives outside of the Dart heap).

@insinfo
Copy link
Author

insinfo commented Aug 3, 2021

@johannphilippe

I don't think this is a solution and that it is efficient, there has to be a native thread implementation to be able to share Objects/Structs

@johannphilippe
Copy link

@insinfo That is what I said. But since it doesn't seem to be in the focus of Dart team, I think it's still useful too try a few workarounds.

@mraleph Never tried that way. I'll try it soon.

@Xyncgas
Copy link

Xyncgas commented Sep 23, 2021

I am screaming for threads too

@mtc-jed
Copy link

mtc-jed commented Mar 4, 2022

On request of @mraleph and following discussion from #46754 with @gmpassos and @mkustermann , here is a proposal : SendPort.sendPointer(Object).
This method would send a pointer to the Object. Object becomes unavailable in the sending Isolate (becomes null ? Implements a particular interface ?).

This would allow the transmission of big, user-defined data across Isolates without serialization, and without Isolate.exit()

The main problem with this approach is of course how to make the Object unavailable.

@xrad
Copy link

xrad commented Jul 22, 2024

This is not new and has been cited in this thread a couple of times.

@junaid1460
Copy link

junaid1460 commented Jul 22, 2024

This is not new and has been cited in this thread a couple of times.

Ack, TLDR; collapsed ones. My bad

@ASGAlex
Copy link

ASGAlex commented Jul 22, 2024

just use another language bro

This is kinda mantra here :-( Yes, they asked you for use-cases and then says that there is no problem in Dart!

@xrad
Copy link

xrad commented Jul 22, 2024

Keep it civil, please. Having work-arounds is better than nothing, I'm sure it wasn't meant to dismiss your use case.

The fact of the matter is that there is currently no support for threads the way many us wanted. If you want to change that, its probably best to join forces around that proposal, perhaps they can use help over there.

And btw, the "whatever" in that work around can very well be Dart as well as another isolate. If you read back a bit more you'll find some more pointers how to make use of the dart:ffi interface. Of course your app's portability might suffer from this.

@maks
Copy link

maks commented Jul 23, 2024

I have a complex Flutter app (Fintech) that both creates charts and runs simulations, testing trading strategies.

dart:ffi + Go/Rust/C/C++/Whatever

You asked for use cases for threading. I provided one such use case. And then you say "just use another language bro"??

I'm starting to think this whole debate about threads is in a phase of denial.

Hardly that. Its simply that you specifically referenced a Flutter app as your use case and given a huge amount of functionality in Flutter already depends on interfacing with native libraries in a variety of C/C++/Java/Kotlin/ObjC/Swift it was simply pointed out that following that existing pattern, if the current functionality within Dart does not provide what you need for your specific usecase, you are free to make use of existing or new libraries written on almost any other language.

@junaid1460
Copy link

I would love to see go channel like implementation. Simple and easy, with dart's language features it would be a killer option for writing servers. Being able to build flutter widget objects on another thread and hand it over to main is a damn good option. But object allocation and GC might be a problem, have to transfer complete ownership of objects, which is hard and dirty. Maybe third thread that just does GC could solve, but ownership transfer etc should be in place. I get why folks are slow on this.

@d-markey
Copy link

For (Web) servers, I'm not sure you really need this. HttpServer can bind several isolates to the same address/port so you already have multiple event-loops handling multiple incoming requests on top of async. I suppose Shelf makes use of this mechanism, I sure know Alfred does.

For what it's worth, you may want to have a look at Squadron. Supports native and Web platforms, JavaScript and Web Assembly targets. Make sure you use squadron_builder to generate the code for all the plumbing. squadron_builder tries to handle as much boilerplate code as possible, but leaves serialization (primarily on Web platforms) a user-responsibility.

</shameless-plug>

@insinfo
Copy link
Author

insinfo commented Sep 23, 2024

In my previous answer I mentioned a use case where it would be useful to have multi-threads with memory sharing

It's not just games or low-latency audio use cases that benefit from a shared-memory threading model, for example simple cases of request counters and extracting other metrics from a WEB application using angel3, shelf_plus, aqueduct, conduit or any other Dart backend framework for Prometheus, you would have to rewrite part of these frameworks for each project to obtain these metrics using the Dart isolated model, whereas with the shared-memory threading model it would not be necessary to modify anything in these frameworks, just use lock for the writing in shared memory or using Atomic Variables just like in C#/JAVA

@d-markey
Copy link

But I wasn't referring to the initial post from 2019, I was just reacting to junaid's post.

@junaid1460
Copy link

junaid1460 commented Sep 27, 2024

For (Web) servers, I'm not sure you really need this

it's about making a language generic enough to build anything with it, I mean why wouldn't you use it in servers? servers aren't just HTTP listeners, they could do lot more, why not tokenize and run llms? why to copy these tokens? There's so many things you could do if there's shared memory and as a programmer you know what you're doing. It's not a specific case of listening to sockets, servers don't end at just that.

Let me give you one more example, I want to write a small database . One would argue saying run it one isolate and then make requests. But what about my db itself, if I know that certain queries in my db can be done in parallel I would choose do that, performance matters here.

@maks
Copy link

maks commented Sep 27, 2024

Let me give you one more example, I want to write a small database . One would argue saying run it one isolate and then make requests. But what about my db itself, if I know that certain queries in my db can be done in parallel I would choose do that, performance matters here.

https://www.erlang.org/doc/apps/mnesia/mnesia.html

@junaid1460
Copy link

https://www.erlang.org/doc/apps/mnesia/mnesia.html

How's mnesia is even an example, have you even used it? I have been using elixir and BEAM in production for last 5 years, don't simply throw things just don't belong in the thread. I can say ETS, even that reads and writes from multiple schedulers, but for what joy?

An exercise for you, try writing something like erlang's scheduler in dart.

We're talking about what can we do, not what's out there. I will paste link for postgres, because why not? my computer can copy and paste.

Screenshot 2024-09-28 at 7 55 39 AM

@maks
Copy link

maks commented Sep 28, 2024

https://www.erlang.org/doc/apps/mnesia/mnesia.html

How's mnesia is even an example, have you even used it? I have been using elixir and BEAM in production for last 5 years, don't simply throw things just don't belong in the thread. I can say ETS, even that reads and writes from multiple schedulers, but for what joy?

An exercise for you, try writing something like erlang's scheduler in dart.

We're talking about what can we do, not what's out there. I will paste link for postgres, because why not? my computer can copy and paste.

@junaid1460 For someone who has been using Elixir and BEAM I'm very surprised then that you don't seem to realise how similar Dart Isolates are to Erlang Processes and while Darts Isolates are missing the powerful pre-emptive scheduler, Isolates have most of the other properties of Processes and the benefits it brings to programming concurrency. Given your whole screed about needing threads, you didn't mention pre-emptive scheduling which is hardly a property of shared memory threading that has been emphasised in this thread. Feel free to peruse the talk I did that shows just how usable large numbers of Isolates with (the now not so new) Isolate groups feature are for safe, non shared memory concurrent programming with Dart. I'll leave finding the link to that talk as an exercise for you.

@junaid1460
Copy link

junaid1460 commented Sep 28, 2024

I'm very surprised then that you don't seem to realise how similar Dart Isolates are to Erlang Processes and while Darts Isolates

No, it's just not. Erlang shares memory, it makes sharing safe by making structures immutable.

powerful pre-emptive scheduler

Look into how preemptive scheduler works, now think can you build it in dart. ( forget it you can't, you can but what's the point if you copy between isolates to achieve it )

See there's a difference between getting things done somehow and getting things done right, having ability fully utilise the hardware without constraints is something we're looking for here, ie: General purpose tool.

@junaid1460
Copy link

I had already given a solid reason why we need this earlier, building a text editor. I have written it in dart, then had to move to c++, the amount of complexity in it requires me to make whole editing immutable so I can do undo/redo.

Say I got the data structures that is required, I have custom piece table implementation here. But what about syntax highlighting. What about some other plugin that lets me color some weird syntax. It just can't happen in another isolate, under millisecond latency is what we are looking at here.

@maks
Copy link

maks commented Sep 28, 2024

I'm very surprised then that you don't seem to realise how similar Dart Isolates are to Erlang Processes and while Darts Isolates

No, it's just not. Erlang shares memory, it makes sharing safe by making structures immutable.

Fine, shared mutable memory, but I have no idea why you make that specific point in the context of this specific issue being threads for Dart which would not be for shared immutable memory, so a rather pointless distinction in the context of this discussion.

powerful pre-emptive scheduler

Look into how preemptive scheduler works, now think can you build it in dart. ( forget it you can't, you can but what's the point if you copy between isolates to achieve it )

What a bizarre thing to say! Where exactly did you see me suggest that you will be able to implement a pre-emptive scheduler in Dart yourself ?? Just like BEAM is what provides preemptive scheduling of process and not you.

See there's a difference between getting things done somehow and getting things done right, having ability fully utilise the hardware without constraints is something we're looking for here, ie: General purpose tool.

Again you keep making these assertions that you can't "fully utilise the hardware" with Isolates, could you provide actual proof of this?

@junaid1460
Copy link

junaid1460 commented Sep 28, 2024

What a bizarre thing to say! Where exactly did you see me suggest that you will be able to implement a pre-emptive scheduler in Dart yourself ?? Just like BEAM is what provides preemptive scheduling of process and not you.

I do not know how to explain it you bro, I feel like talking to a wall here. It's not what is provided and what is not. "It is ability to provide something without requiring us to do this long conversation here in this thread"

Look at rust, go. They do have their own philosophy, but they do support unsafe contexts where you do whatever you want to do because some times you just need these "potentially unsafe" constructs to get the best out of the system.

Fine, shared mutable memory, but I have no idea why you make that specific point in the context of this specific issue being threads for Dart which would not be for shared immutable memory, so a rather pointless distinction in the context of this discussion.

Read my second comment, read lots of comments on why this is needed that has been written on this thread before this.

Again you keep making these assertions that you can't "fully utilise the hardware" with Isolates, could you provide actual proof of this?

Again, Read my second comment, read lots of comments on why this is needed that has been written on this thread before this. if it wasn't the case this thread would not exist.

@maks
Copy link

maks commented Sep 28, 2024

Say I got the data structures that is required, I have custom piece table implementation here. But what about syntax highlighting. What about some other plugin that lets me color some weird syntax. It just can't happen in another isolate, under millisecond latency is what we are looking at here.

Why is 1ms latency a hard requirement? In Flutter applications, we deal with max 16ms per frame and Isolates work for a large number of Flutter app usecases. Likewise are you aware that zero-copy for data returned from an Isolate has been available since 2.15:

In 2.15 the worker isolate can call Isolate.exit(), passing its result as an argument. The Dart runtime then passes the memory containing the result from the worker isolate to the main isolate without copying, and the main isolate can receive the result in constant time.

Likewise as time goes on, Darts implementation Isolate performance has been improved as issues are identified and fixed. Out of interest you can see the benchmark that was posted before that issue was fixed already showed that spawning and using large numbers of short lived Isolates was already doable: 0.6ms overhead on a very old mac * again before* the issue was addressed.

@maks
Copy link

maks commented Sep 28, 2024

I do not know how to explain it you bro, I feel like talking to a wall here. It's not what is provided and what is not. "It is ability to provide something without requiring us to do this long conversation here in this thread"

I am not your "bro"

Look at rust, go. They do have their own philosophy, but they do support unsafe contexts where you do whatever you
want to do because some times you just need these "potentially unsafe" constructs to get the best out of the system.

As has been pointed out previously, this is likewise already possible in Dart with Isolates too.

Read my second comment, read lots of comments on why this is needed that has been written on this thread before this.

Again you keep making these assertions that you can't "fully utilise the hardware" with Isolates, could you provide actual proof of this?

Again, Read my second comment, read lots of comments on why this is needed that has been written on this thread before this. if it wasn't the case this thread would not exist.

I've read your comments carefully, they in no way demonstrate anything close to what you are asserting so I don't feel that replying to you further will progress this conversation in anyway and will simply spam all the other subscribers of this issue.

@junaid1460
Copy link

junaid1460 commented Sep 28, 2024

Why is 1ms latency a hard requirement? In Flutter applications, we deal with max 16ms per frame and Isolates work for a large number of Flutter app usecases. Likewise are you aware that zero-copy for data returned from an Isolate has been available since 2.15:

Yes, if your application only does one thing, I assume whole world works like that?

Likewise as time goes on, Darts implementation Isolate performance has been improved ashttps://github.com/dart-lang/sdk/issues/50789 and fixed. Out of interest you can see the benchmark that was posted before that issue was fixed already showed that spawning and using large numbers of short lived Isolates was already doable: 0.6ms overhead on a very old mac * again before* the issue was addressed.

Yes for sure, nobody denies it, but that has nothing to do with why we need shared memory.

Look at rust, go. They do have their own philosophy, but they do support unsafe contexts where you do whatever you
want to do because some times you just need these "potentially unsafe" constructs to get the best out of the system.

As has been pointed out previously, this is likewise already possible in Dart with Isolates too.

Show it to me, edit one class member, in two different isolates at same time.

@junaid1460
Copy link

I've read your comments carefully, they in no way demonstrate anything close to what you are asserting so I don't feel that replying to you further will progress this conversation in anyway and will simply spam all the other subscribers of this issue.

Only thing I get from it is you threw some random balls at court, without knowing any crux of it and went on gaslighting the original need by saying isolates are better.

@d-markey
Copy link

I had already given a solid reason why we need this earlier, building a text editor.

I question the solidity of that reason. There are dozens text/code editors written in JavaScript out there. They don't need threads + mutable shared memory.

@junaid1460
Copy link

I question the solidity of that reason. There are dozens text/code editors written in JavaScript out there. They don't need threads + mutable shared memory.

Let's not say JS. Let's say, JS, wasm, and mainly the sorted thing is HTML and CSS. And what happens to it when you open a very large file?

@junaid1460
Copy link

junaid1460 commented Sep 28, 2024

I can't really understand, why people throw random names, instead of going and building it themselves and realising how painful it is, it's very easy to throw names of things that worked on for years. They do this, that app does this, that's not really something debatable.

I am telling you, build your own Rope structure or Piece buffer. When you hit save what is the logical thing you should be doing? if file is 100 megs, should you wait until file written to accept any new keystrokes ? ( Think of this in context of dart )

@Eglusaxie
Copy link

I think this issue may not be about a dispute over the technical route.
Is it possible that this is simply a matter of cost-benefit ratio?
Historically, early stubbornness or laziness often becomes a troublesome burden in the future.

@Eglusaxie
Copy link

Eglusaxie commented Sep 28, 2024

I think this issue may not be about a dispute over the technical route. Is it possible that this is simply a matter of cost-benefit ratio? Historically, early stubbornness or laziness often becomes a troublesome burden in the future.

What I said is likely wrong because I'm a novice programmer. Anyway, this issue is making me consider giving up Dart and Flutter, especially since there seem to be another options now: Kotlin and Compose Multiplatform.

@xrad
Copy link

xrad commented Sep 28, 2024

@Eglusaxie you mean just in case this thread wasn't controversial enough? 😂

@Eglusaxie
Copy link

you mean just in case this thread wasn't controversial enough?

I think opinions on this issue depend on people's understanding of how operating systems and hardware work.

@mraleph
Copy link
Member

mraleph commented Sep 30, 2024

Folks please keep it respectful and on point. This absolutely not a place to bicker with each other. You are welcome to find other channels for that if that's something you wish to do in your free time.

We are actively investigating different ways to open the pandora box of shared memory multithreading. You can follow the most recent variant here: #4095

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests