4 ms·
Eventually we come to a point where I agree with you, almost. One exception is Redis/Node.js - I don't like them because they indeed work in certain cases, but
by mdomans 10y ago
Eventually we come to a point where I agree with you, almost.
One exception is Redis/Node.js - I don't like them because they indeed work in certain cases, but that set is much less than what authors of Redis/Node.js advertise.
I very fondly, for example, remember antirez being adamant that Redis is awesome as cache, yet it took me 10minutes to prove that single Redis performs worse than single Memcached. And no, I don't consider answer: run more Redis instances valid. You design software to have features that solve problems, not replace old with new.
And yes, Erlang uses message passing and has locks and immutable memory.
I prefer the Go approach of mutating through channels/queues. Both Go and GCD in C/ObjC are good examples of this approach.
- btilly 10y agoIf your use case says that it is OK for data to disappear on you at random, then Memcached is great. Otherwise it sucks. If the amount of data to cache is big enough to use up available RAM, then Redis is going to suck. If your use case involves complex data structures populated over here that you want replicated there, then Redis might really be good for you. Know what each tool is good for, and don't believe unwarranted hype. And yes, coroutines have their place. Python without generators would be a much weaker language.
- mdomans 10y agoIt's not hype really - it's me getting fed up with authors arguing that their software solves every problem. Redis is very good at being data structures store. In regard to Python - generators make sense, coroutines, much less. That's my opinion, but over the span of 10 years most programmers I met professionally either never used coroutines outside of pet projects or use them sparingly. I'd actually like to see a big project with coroutines implemented using the async/await.
- btilly 10y agoI disbelieve. Take working in Tornado. I've been writing in Tornado, and all I've needed to do is decorate functions with @gen.coroutine then use generator syntax. All the detailed plumbing to implement the event loop is done for me, and I never interact with it directly. Nor would there be any value in my doing so. It needs to be implemented once, and implemented well. Once that is done there is little to no value in messing with it. You'd just be creating the opportunity for disaster with little to no corresponding value. I actually experienced this exact disaster. In this project, Tornado has to interact with Redis. So I used tornado-redis which tried to be implemented directly. Unfortunately it was not well implemented, and one coroutine could easily get a message meant for another. Untangling the mess promised to be a lot of work. However it was literally the work of minutes to switch my class to the synchronous Redis library, write a ThreadPoolExecutor wrapper for my class, and have Tornado interact with that. It would be slightly better if the native version had worked, but this got 95% of the benefit for under 1% of the work. You could describe this as "using coroutines sparingly". I'd describe it as using them sensibly. Coroutines are a useful bit of plumbing to enable a programming style, but their flexibility is also a burden. You should use them to build a sensible abstraction, then use that. For another example of this, look at Scheme. Scheme internally implements continuations, and function calls are just a special case of that. Continuations are, of course, a building block for coroutines, generators, and many other programming constructs. However a sensible Scheme programmer just implements functions. They may be using a project that somewhere does coroutines, continuations, and all sorts of other fun stuff. But the day to day code you write doesn't do that. There is no need to add the mental overhead from using the construct all of the time "just because it is there".
- mdomans 10y agoTo a certain (high) degree I agree. First of all, when I'm wrote this article by coroutines I meant specifically Python async/await pattern which I don't find easy to use or read. And I agree on Tornado. Over the years I've seen many APIs that abstract away stuff like implementation details of cooperation yet are in fact coroutines - e.g. goroutines in Go, tasklets in Stackless. Even Erlangs processes are, on the VM level, cooperatively scheduled green threads. For me there are 3 problems when you design concurrency APIs. One is performance and language internals. Second is API that you expose to the end programmer. Third problem is what you can achieve as a programmer using those API based on how integrated concurrency is into the language. All the examples of higher level platforms I know are good for highly concurrent apps: Erlang, Go, Node.js, GCD - they were designed and throughly integrated into the language. In that context threading in Python really feels bolted on. And for something different: seeing how some people reacted I'm diving deep to make 2-3 articles of tour-de-concurrency. What do you think?
- mdomans 10y agoAlso, I've been thinking on what you've written about cooperative multitasking OS'es and why preemptive concurrency took over. Cooperative multitasking is easier in regard to design of OS or language that implements it - but honestly, almost all production code today is glue logic and almost every app is big and messy - e.g. XCode takes ~150MB just to start on my Mac
- btilly 10y agoThere is that. And the fact that it is straightforward to extend an existing preemptive system to handle multiple CPUs, but not obvious how to do it with cooperative ones. That said, there are many possible trade-offs between preemption and cooperation. It is old, but http://www.bitmover.com/llnl/smp.pdf http://www.bitmover.com/llnl/smp.pdf made a good case for why SMP was the wrong way to scale to large numbers of CPUs. NUMA is a much better architecture. SGI demonstrated this in the 1990s with 1000 CPU machines. Unfortunately Linux took the SMP path like Solaris before it, and our performance is suffering as a result. :-( An interesting historical note. Larry McVoy's thinking about how to handle contention lead him to thinking about a very, very slowed down version of it - distributed source control. This lead to a "side project" named BitKeeper. Move a few years later and that was a real product used for the Linux kernel. After some drama, he withdrew permission for Linux to continue using it for free and in response Linus wrote git. (Linus and Larry were always on good terms. The drama was between Larry and Jeremy Allison, of SAMBA fame.)