4 ms·
> there are far better ways of avoiding it than these anti-patterns. Could you describe or at least point to some of them?
by mstromb 12y ago
> there are far better ways of avoiding it than these anti-patterns.
Could you describe or at least point to some of them?
- pron 12y agoLightweight threads. They make blocking free, and allow using constructs far more suitable for imperative languages. They don't destroy your stack traces, and don't require you to re-invent exception handling and control flow. Instead of promises -- simple blocking calls (or blocking futures in some cases); instead of observables -- blocking queues (aka channels). Instead of reaching out for ways to avoid blocking, we just make blocking free.
- tunesmith 12y agoSo, the actor model is an anti-pattern? Like Akka in Scala?
- deleted 12y ago[deleted]
- pron 12y agoSee my reply to eranation
- eranation 12y agoDo you mean co-routines / user threads / green threads? I tend to agree it can have a serious performance boost in some cases. Not sure why you were down voted. There is actually a library for java that adds it via byte code instrumentation (quasar or something) although not sure it will work for scala. But saying that actor model is bad practice, I'm not sure that I accept it. Maybe on a single muticore but once you start talking distributed computing (e.g. Spark which is Akka based) then all this "avoid crossing to the kernel" optimization is becoming a drop in the ocean.
- jamii 12y ago> all this "avoid crossing to the kernel" optimization is becoming a drop in the ocean Here is an example of a small single threaded program beating out a number of distributed graph frameworks running on 128 cores, with a 128 billion edge dataset. http://www.frankmcsherry.org/graph/scalability/cost/2015/02/04/COST2.html http://www.frankmcsherry.org/graph/scalability/cost/2015/02/... Performance matters because it enables simplicity. If your language forces you to pull in multiple machines to solve your problem then its turned a simple program into a distributed system and life gets complicated fast. Just throwing more cores at a program without understanding why its slow will just get you into trouble. Multithreaded programs and distributed programs should be a scary last resort after making absolutely sure you can't get away with the simple solution.
- eranation 12y agoYes I saw this, and got a little disillusioned at first, but after looking carefully this is not big data, their entire dataset fits in RAM. When your dataset can't fit in RAM - this is where the last resort comes into play. Sadly most companies, I agree, don't know when data is really big data. Most of the time it's just medium data. And I agree about the overhead costs.
- jamii 12y ago> their entire dataset fits in RAM 128 billion edges. 1 TB of data just to list edges as pairs of integers. 154 GB after cleverly encoding edges as variable length offsets in a Hilbert curve. Do you have a bigger dataset?
- eranation 12y agoOh, I was referring to the original posts. Will take a look. Thanks!
- pron 12y ago> Do you mean co-routines / user threads / green threads? I tend to agree it can have a serious performance boost in some cases. Yes, but in this context, they provide the same performance benefits as the asynchronous techniques mentioned in the article, without all the drawbacks of the cumbersome asynchronous style. > But saying that actor model is bad practice The actor model is a general technique for fault-tolerance, and it's great. How it handles concurrency, though, is an orthogonal concern. Akka has asynchronous (callback based) actors, and callbacks are an anti-pattern. Erlang has synchronous (blocking) actors, which are so much simpler, and don't have all the complications associated with asynchronous code.
- EdwardDiego 12y agoWhy are you being downvoted for a constructive comment? "Free blocking" was what attracted me to Erlang's actors in green threads as opposed to Akka's actors that block entire threads when they block.
- modarts 12y agoLike C# (and now ES7's) async/await?
- pron 12y agoNot quite. async/await are what's known as stackless coroutines, and require explicit usage. Lightweight threads, aka user mode threads, aka fibers, are simply threads that have negligible (or no) cost associated with blocking. Examples include Erlang processes, Go goroutines and Quasar fibers.
- mpweiher 12y agoYes. And in fact we can even use kernel threads most of the time. However, there is one thread you don't want to block: the UI thread. We do need ways of getting things to the UI asynchronously.
- pron 12y ago> And in fact we can even use kernel threads most of the time. Well, not if you need tens-of-thousands of them or more. > However, there is one thread you don't want to block: the UI thread. No problem. You simply multiplex fibers onto the UI thread, where they can block all they want. Here's an example in Quasar (Java): FiberScheduler uiScheduler = new FiberExecutorScheduler("UI-scheduler", task -> EventQueue.invokeLater(task)); // schedule on the UI thread new Fiber(uiScheduler, () -> { for (i = 0;; i++) { assert EventQueue.isDispatchThread(); // I'm on the UI thread! uiLabel.setText("num: " + i); // I can update the ui Fiber.sleep(1000); // ... yet I can block all I want } }).start();
- mpweiher 12y ago"most of the time" we don't need tens-of-thousands of threads. Yes, I can easily dispatch something onto the UI thread using the technique you describe, but for that using a simple HOM is much more convenient: uiLabel onMainThread setText:'num: ', i. Neither this nor your example are actually blocking the UI thread, because they are really just incidentally there and just pushing data in, a quick in/out. (And I assume that "Fiber.sleep()" takes the Fiber off the main thread ) However, the more difficult part is if the UI thread actually has control flow and data dependencies, let's say a table view that is requesting data lazily. Taking the blocking computation off the UI thread doesn't work there, because the return value is needed by UI thread to continue.
- muraiki 12y agoBy "tens-of-thousands of threads" I think he means something along the lines of how in Erlang/Elixir an object is often a thread, and a library a program. By giving so many threads "for free" you make blocking cost nothing. It's a very different approach from your typical language. This article only uses a few threads, but it will perhaps quickly give you an impression of how this design works: https://howistart.org/posts/elixir/1 https://howistart.org/posts/elixir/1