Now with the security exploits many plugins have exposed and the way a misbehaved thread can bring the whole application down, we are moving back to the multiprocess model as a better sandbox model.
Old becomes new as they say.
Now with the security exploits many plugins have exposed and the way a misbehaved thread can bring the whole application down, we are moving back to the multiprocess model as a better sandbox model.
Old becomes new as they say.
Shared memory (be it shm/heap in same process) with associated mutexes, semaphores, locks and the like is a right pain to get right without introducing race conditions, deadlocks etc.
Go is interesting as it uses "micro threads" (goroutines) and message passing CSP style but I haven't found a use for it yet.
But is also has shared heaps by default. So you still have to rely on everyone being an "adult". I wish shared heaps would have been a specially enabled feature not the default. But I guess the language was position to compete with C++ and Java and isolated heaps would have provided a performance decrease in benchmarks -- and thus people's willingness to adopt it.
For large concurrent systems, safety and fault tolerance often leads to their failure but it is kind of hard to encode that in a quick benchmark to impress people.
Here are a few languages/systems with default isolated heap runtimes between concurrency units: Dart's isolates, Erlang's processes, Nimrod's threads, Web Workers in modern browsers. Anyone know of more?
http://dlang.org/migrate-to-shared.html
http://www.informit.com/articles/printerfriendly.aspx?p=1609...
> and no threads in favour of "select".
Not sure why you mentioned that. Callback chains can create concurrency contexts (callback chains) that can interfere with each other, much like multiple threads would. It would have a much higher granularity but you are not out of the woods.
That is true but you only have one thread to synchronise so mutexes and locks are vastly simplified.
Rust's "tasks" feature isolated memory, and, thanks to the magic of linear types, passing data from one to another is both statically-guaranteed to be safe and is never more expensive than the cost of copying a pointer.
Well, if you're passing something that is pointer size, yes. But say, `chan.send([0u8, .. 1_000_000])` will do at least one 1 MB memcpy to load that into the stream, and a 1 MB memcpy to load it out of it when `.recv()` is called.
I hope to someday see the language at least do the opposite, have a specially-declarable "isolated" goroutine. In theory, the compiler ought to be able to analyze a goroutine, determine that it shares no data at startup with another process (i.e., nothing in a closure or something), determine that it only communicates via value-passing channels (which courtesy of my previous restriction, can be analyzed by simply looking at what channels are passed in at startup time, and some analysis of the types of the channels), and thus guarantee that at least this goroutine is fully isolated. Pervasive usage of the new keyword I'm hypothesizing would allow a diligent programmer to recover most of the isolation advantages without having to rewrite Go entirely. It also ought to enable some other optimizations against these guaranteed-isolated goroutines, the biggest of which is that they no longer need to participate in a global stop-the-world GC, both in that they can continue running while that is occurring and that they also relieve the global GC from the task of scanning over them.
(In fact all the analysis ought to itself be fully automateable, and the user shouldn't have to declare it; I'd want them to still have the option to make a declaration so the compiler can tell them if they screwed up, though. I don't like such critical functionality being behind an opaque optimizer.)
But this certainly won't happen soon; there's a large enough list of stuff that comes before that.
That would preclude sending interfaces over channels (along with any other existential or mutable reference type), because the type system doesn't know whether the interface is closing over shared state. Not being able to send interfaces over channels would mean that channels would be restricted to only one kind of type, because Go doesn't have discriminated unions so interfaces are the only way to perform type-switch. Those goroutines would be so restricted as to be almost useless.
You cannot just bolt isolation on after the fact. You must design your language for it from the start.
That said, Go's race detector is very good and it's awesome that they focused on getting first-class support for runtime race detection so early.
Yes, I agree, and I'm sure I'm going to have many years of wishing they had. At the moment I don't have a better entrant in this field that is palatable to my coworkers, though. They've rather disliked Erlang (and not for lack of trying, and not for lack of good reasons, for that matter), Haskell's right out, and I'm running low on production-quality true isolation-based languages here. Several additional up-and-coming contenders; I'm sure if I could have used Rust-from-2018 I'd take that in a heartbeat, but, alas, it's 2013.
Go is tolerable, at least the way we're using it.
may you please elaborate on reasons for not using Erlang ?
It's a brilliant language that was well ahead of its time, and I don't mean that merely as a "I want to be nice" parting comment; it is a brilliant language that was ahead of its time and every serious language designer should study it until they deeply understand it. Indeed, I will absolutely attribute a significant portion of my success in programming Go to the wisdom (no sarcasm) I learned from Erlang, and Go would be a better language today had the designers spent more time learning about it first. (It still wouldn't be an Erlang clone, but it would be a better language.) But it's just become increasingly clear that it has been a drag on my project, for a whole host of little reasons that add up. It was the right decision at the time, because virtually nothing else could do what it did when I started, but that's not true anymore.
Someone will be tempted to post a point-by-point rebuttal. My pre-rebuttal is, I've been programming in it for six years (so, for instance, if there's some "magic solution" to clustering that has somehow escaped my six years of Googling, well, I think I did my part), yes, I know all other languages will also have "little things" (and big things), and Erlang may be perfect for your project, absolutely no sarcasm.
Tcl runs an interpreter per thread and communicate each other using message passing.
When you have multiple processes talking to another then, unless all your RPCs are completely stateless, you still need to orchestrate synchronisation in some form. There's also the problem that in 2013 we still don't really know how to do IPC/RPCs really well, and doing so portably is hard (Notice Mozilla are writing their own from scratch)
It's all very well new languages coming along and solving the trivial stuff (setting up message queues, isolating memory) but very few of them do anything to solve the real problems.
The "let it crash" model from Erlang and micro-kernels.
Still you are right, we are far from having an acceptable solution that we could apply everywhere, so to say.
I think that Rust makes a lot of effort to move things in the right direction. In Rust you can share memory, but unless you are in the unsafe sublanguage (which is clearly marked) the type system restricts you to one of: (1) copying messages; (2) transferring ownership of a message so that the original thread cannot race on it; (3) sharing immutable memory only; (4) taking a lock before accessing mutable data. We've seen huge engineering benefits from this: making parts of Servo thread-safe has been simply a matter of running the compiler repeatedly and letting the error messages tell us where to insert the locks; when it compiles we know the data races are gone. (You can still deadlock though.)
Just imagine the performance impact of something like Eclipse if each plugin was a separate process using message passing.
Maybe it is doable, not sure. Anyway I rather favor safety over performance.