Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I was debating writing a blog post like "Blocking IO Considered Harmful" or something cheeky like that.

I'm not as familiar with Rust or C as other people, but I've done a lot of Java, and JDBC has made my life more difficult than it needs to be due to its semantics. It has been hard for me to get decent thread utilization with it because of all the blocking it does behind the scenes.

I've moved most of my SQL stuff to Vert.x SQL, which has given me better performance overall, and I can do most of it with a single thread.

At least in Java land, it's trivial to convert a non-blocking call into a blocking one (in Vert.x you can do myFuture.toCompletionStage().toCompletableFuture().get()), but it's pretty hard to efficiently go the other direction. I really wish JDBC would create something like "executeAsync" that returns a CompletableFuture or something similar.



In defense of Java blocking calls, in the 1990s to the 2010's the industry mostly considered Asynchronous programming as coordinating multiple threads over know yield points - such as using atomic locks, or mutexs. The main push by the industry was all about abstractions and OOP, and moving away from static C/C++ programming languages to dynamic programming languages such as Java/Python/Visual Basic or C#.

It is only until recently with the popularity of Node.js, Python and the explosion of the web that the developer have to deal with single threaded languages that blocking calls are a significant impact to the users experience. This push for Async in the web has had a cascade effect to system programming languages where old time developers are only first learning about it.


Could you clarify the "static C/C++" vs "dynamic Java" distinction? I'm used to thinking of "static" and "dynamic" in the context of type systems, but do the terms have overloaded meanings in concurrency/parallelism?


The push for async as we know it started in .NET, initially with F# and then popularized by C#, with the pattern then adopted by JS, Swift, Python, Rust and other languages. The implementations, however, are wildly different.


I thought F# was a derivative of OCamel that focused exclusively on immutable data structure and functional programming, instead of mutable/imperative languages.



It was also pushed by the C10K movement.


True, one great thing that did come out from it is that the language needs to natively support asynchronous programming with syntactical sugar otherwise you get an explosion of libraries/frameworks that solve the problem with their own problems. How-ever this is a chicken/egg problem, did everyone really need async or did it come about because the proliferation of frameworks to solve this common pattern?


I can’t use the Vert.x SQL lib for MSSQL because named instances and Kerberos auth aren’t supported, so for a good deal of web calls I use the MSSQL JDBC inside executeBlocking Vert.x blocks.

However, recently I was thinking of utilizing a Vert.x worker verticle with a pool of Java virtual threads that could serve my JDBC calls. Has anyone tried anything like this?


> I really wish JDBC would create something like "executeAsync" that returns a CompletableFuture or something similar.

Relevant: https://github.com/jasync-sql/jasync-sql#getting-started


Yeah, vert.x SQL is similar, which is what I am using.


Does your issue (which can be solved with JDBC creating executeAsync that returns a CompletableFuture) go away with virtual threads?


Probably for someone competent, though I had trouble getting the performance I wanted out of that as well when I tried it.

I’m not sure if my issues come from the use of blocking APIs at the lower level, or if I’m just doing something dumb. Neither would surprise me.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: