3 ms·
> But I can't see how it's less complex than linear code. I am being misinterpreted here (in a peculiar way that has happened before on HN...). I wrote that it
by arghwhat 9y ago
> But I can't see how it's less complex than linear code.
I am being misinterpreted here (in a peculiar way that has happened before on HN...). I wrote that it does not increase the complexity "in any measurable fashion".
It seems that you interpreted this as "concurrency is less complex than non-concurrency", when in reality I am saying "concurrency is a tiny bit more complex than non-concurrency" (extra emphasis on "tiny").
Now, back to the topic:
Asynchronous programming is strictly speaking the simple idea that code will be run later when some conditions are met. For example, running a callback when a network response is received from the "fetch" API in modern JS, with all I/O handled behind the scenes by an event engine of sorts.
I do not believe that this concept provides any measurable increase in cognitive load. You only concern yourself with these devices where they are used, and they are extremely simple to wrap your head around.
In another model, you may have full parallelism and shared memory access, in which case you need to be more careful to only use thread safe structures. Even then, unless you do something stupid™, everything is fine, and the cognitive load is increased globally but only mildly so with a model similar to goroutines and channels.
Finally, you may have to design and use synchronized/atomic data structures, in which case things increase in difficulty. While this does increase cognitive load in a small area of the code, I does not increase the cognitive load over the entire application. However, just like not all application need to design a cryptographic protocol, not all applications need to design concurrent data structures even if it uses concurrency. Thus, one should additionally note that this localized overhead is not a universal overhead of all concurrent programming.
BTW, I do not find that goroutines present less cognitive load than pthreads ("threading") and a CSP library. They simply present syntactic sugar for a better developer experience. They also give an M:N threading implementation unlike pthreads, but that's an implementation detail.
- wpietri 9y agoSorry, but I'm just not seeing it. Having a magic, behind-the-scenes event engine with a queue containing an unknown number of items executing in unpredictable order seems definitionally way more complex than not having any of those things and running the code in strict linear order. Performance is way better, sure, but at a cost of complexity and cognitive load. Sure, the difference is tiny if everything works smoothly. But if everything worked smoothly, we wouldn't have jobs.
- arghwhat 9y agoThis is a bogus argument: "abstractions are complexities and lack control". This argument can be equally applied to any other abstraction or convenience functionality, such as garbage collectors (unpredictable destructor execution, resource consumption and performance), OS schedulers (unknown number of items executing fighting for time quanta, unpredictable performance, unpredictable latency), high-level languages (unpredictable code generation, lack of ability to express proper intention related to processor abilities), etc. However, the problem here is that your expectation of the abstraction is wrong, not that they introduce complexities. Furthermore, all abstractions give up control to the abstractions so that you do not have to concern yourself with it. You cannot both have full control over functionality and not concern yourself with the functionality. An even engine is a scheduler like the OS scheduler. It is designed to take care of scheduling, making it not a concern for you, hiding the implementation (effectively making it "unpredictable"). If you want control, you have to give up the abstraction and go straight on the iron, just like you would have if you want precise memory behavior. However, considering this a "complexity" would be wrong. There is nothing complex about asynchronous programming's lack of predictable execution order. The contract is that the code will execute when the event arrives, nothing else. This is by no means a complexity. In many engines, the execution of your code isn't even concurrent, only having I/O run in the background. (I am intentionally ignoring buggy event engines, just like we ignore buggy GC's, kernels, compilers, CPU's, etc.)