6 ms·
> You probably should be using something a bit higher level. While there's nothing wrong in using something higher level, the main reason for using higher leve
by Skinney 4y ago
> You probably should be using something a bit higher level.
While there's nothing wrong in using something higher level, the main reason for using higher level libraries are because using threads doesn't scale past a certain point.
The problem with libraries that try to work around the scalability issue is one of compatibility. Using co-routines is great, but you need workarounds when targetting JDBC or a Http client. You have to be using coroutines, or coroutine friendly code, everywhere, or you risk reducing performance.
For this reason, we just use regular threads and threadpools in our projects. Once Loom lands we'll change the executors to spawn virtual threads and then we'll be done.
That said, coroutines shine if you can't wait for Loom to land or if you're targetting something other than the JVM (like Android).
- jillesvangurp 4y agoI think you have a wrong concept of what kotlin co-routines are and are assuming limitations that it simply does not have. Anything you can do wit threads, executors, etc. You can trivially use with co-routines. Better still, mostly it uses those things directly and there is no performance overhead. I've used co-routines with: - spring flux - hibernate & jdbc (not a problem, you just use your connection pool as usual and use a threadpool based coroutine context to ensure you don't block your asynchronous request handling main thread. You might prefer switching to some more modern versions of that that support asynchronous IO though. But that stuff is still relatively new and many people stick with blocking IO for this for now. Not in any way a show stopper for using co-routines. - apache httpclient with synchronous IO and a connection pool (same thing basically). - apache httpclient with asynchronous IO (very easy to integrate it's callbacks with suspendCoroutine { ... }) - redis (both synchronous and asynchronous) - mongodb - Java stream API (there are loads of Java libraries that use that) I get it, some people don't want to switch language. So, stick with Java. But do it for the right reasons. Performance really isn't one. Anything Java does, Kotlin can do too. And generally about as fast by virtue of simply using the exact same things in the standard library. And generally without the boilerplate and a lot of syntactic sugar (i.e. it's nicer). Probably if the Kotlin version of something is slower than the Java version, it's because you are doing it wrong. I can't really think of a lot of cases where that would not be easy to fix. I've seen my fair share of buggy Thread based Java logic over the years; trust me co-routines are way nicer than that. You can still get into trouble with them of course (and mostly for the same reasons). But it covers all the bases pretty well and generally does a better job of keeping you out of trouble.
- Skinney 4y ago> think you have a wrong concept of what kotlin co-routines are and are assuming limitations that it simply does not have. What I’m referring to is this: > you just use your connection pool as usual and use a threadpool based coroutine context to ensure you don't block your asynchronous request handling main thread. For everything that is not coroutine compatible out of the box, you need to do something like what is described above. When porting an existing application to coroutines, you also have to identify the places you need to introduce thread pool backed contexts and use them approprietly. You also need to setup these thread pools correctly so that you don’t end up using more threads than if you didn’t target coroutines. For us, this extra complexity wasn’t worth it. If we were making an app from scratch and could choose coroutine friendly solutions for everything from the start, that would be different, but porting a legacy app to coroutines hasn’t been a good experience. Fortunetly, project loom means all our current thread-based code will be just as scalable as coroutines in the not-to-distant future. That also means we can spawn more (virtual) threads and see a nice speed increase as well. Btw, we’re already using kotlin for most code, just not coroutines.
- jillesvangurp 4y agoOK, I get you don't want to do the work to migrate an existing Java application. It's a lot of work. If you don't have a lot of problems with it right now, you could just leave the code as is. But just so you know, what you are describing is code that is currently boiler plate heavy in Java and essentially making it a lot simpler and easier to reason about with Kotlin. I think you are confusing problem and solution here. In any case, this is how you create a CoRoutineContext backed by a thread pool. val myContext = newFixedThreadPoolContext(100,"db-context") That's it. There's nothing else to do but "use it". There's no need to call shutDown. Or have some thingy to intercept uncaught exceptions. Or have a lot of boiler plate around using it. a simple launch(myContext) { ... } does the job.
- Skinney 4y agomost of our thread pools are long lived, so we don't ever shut them down. When the pool is not long lived, we have a try-with-resources wrapper which handles the shutdown. Most of the time, we do calls to .execute and then join the different threads at the end. The code running within the threads represent the majority of our code, so the boilerplate you're talking about might 10 out of 2000 lines. Our only problem is the number of threads we can spawn safely, and that limit is removed with loom.