You had me until you said Asynchronous I/O is faster than Synchronous I/O in Java. http://www.mailinator.com/tymaPaulMultithreaded.pdf
The Rob Van Behren slide is priceless: dude started building an async server and at the end realised he wrote the foundation for a threading package. I once asked myself the same question and did a little micro benchmark https://github.com/alpeb/io_benchmarks concluding IO was faster. Even so, I ended up doing all my stuff in Scala+Play because it's an immense pleasure and it's so easy to scale.
An Opinionated Guide to Modern Java, Part 3: Web Development
141–150 of 168 posts
Re: An Opinionated Guide to Modern Java, Part 3: Web Development
#142It's great to see how Java web development has progressed. I tried to make a Spring MVC web app work like a decent, modern, readable and productive web application two years ago and it just wasn't possible. Anyone interested in modern JVM web development I would still advise to invest time in learning Scala (or Clojure). They can work with your legacy code and libraries, but my productivity and general joy in program…
That was exactly my experience. Maintaining Java code from time to time makes me realise just how big the difference is.
Re: An Opinionated Guide to Modern Java, Part 3: Web Development
#143Earlier quoted context omitted.
> And unlike him, I have a 30,000 line scala production project under my belt. Everything he says is true, and then some. Ever split up a file into chunks because intellij can't edit it effectively? I have a 20k line Scala project in production and editing it has certainly never been an issue. Why does Intellij have problems with large files?
I've written several large Scala projects and never had Intellij choke on large files.
Re: An Opinionated Guide to Modern Java, Part 3: Web Development
#144Earlier quoted context omitted.
With lightweight threads you can spawn as many fibers as you like. Creating and starting a new fiber is basically free. You can start fibers and join them, in any dependency tree structure. Of course, you can keep using futures (what I call semi-blocking API), only futures that block the fiber rather than the thread, when you join them.
Okay so to run operations in parallel you have to go back to futures, and for more complex dependencies you would need callbacks/transforms. So this means with fibres you could use the simpler synchronous model for serial operations, but future model for parallelism, i.e. a hybrid model. My thoughts are that it might be simpler to adopt a single model rather than two. On the flip side you could argue that with fibres…
Of course you can have long-running fibers that interact with one another through channels. See: http://blog.paralleluniverse.co/2014/02/20/reactive/
Re: An Opinionated Guide to Modern Java, Part 3: Web Development
#145It's funny. An "Introduction to Modern Java Web Development" sounds like a primer for the Play Framework, Scala, and Akka. Each of the examples looks like the starter documentation for Play, in that you've got your json manipulation, routing, connecting to a database, DI, actors, etc. Java devs-- you seriously owe it to yourself to spend the time investigating and ramping up onto Scala and Play. This is where the fut…
I don't know. I loved Play Framework 1. Simple, lean, and lightning fast development. Play 2 came out and it looked strange, with various Scala things mixed in. It's a lot more complicate and bloated, and more buggy. The core piece is in Scala. The build is now sbt, yet another different thing to maintain. The template is Scala, slow to develop and slow to compile. The much-touted async feature is a meh. Most web app…
Re: An Opinionated Guide to Modern Java, Part 3: Web Development
#146You had me until you said Asynchronous I/O is faster than Synchronous I/O in Java. http://www.mailinator.com/tymaPaulMultithreaded.pdf
It's highly cited "paper" and just as wrong. Blocking I/O is implemented via poll(), NIO is epoll. Blocking IO has to copy the array at last once (on the stack for Blocking IO cannot have predictable latency under load at very least, you are left at the mercy of OS thread scheduler. Due to various reasons (e.g. mutator threads should not block GC and compiler ones) thread priorities are honored. I'd argue that a well…
Re: An Opinionated Guide to Modern Java, Part 3: Web Development
#147Earlier quoted context omitted.
Okay so to run operations in parallel you have to go back to futures, and for more complex dependencies you would need callbacks/transforms. So this means with fibres you could use the simpler synchronous model for serial operations, but future model for parallelism, i.e. a hybrid model. My thoughts are that it might be simpler to adopt a single model rather than two. On the flip side you could argue that with fibres…
If you want to run operations in parallel and then "join" them, you need some joining mechanism. A fiber itself can be joined and return a value, so in Quasar, Fiber implements Future. But that's semantics: with fibers, if you want to run operations in parallel, you spawn more fibers; if you then want to join those operations -- you join the fibers. Of course you can have long-running fibers that interact with one an…
Re: An Opinionated Guide to Modern Java, Part 3: Web Development
#148Earlier quoted context omitted.
It's highly cited "paper" and just as wrong. Blocking I/O is implemented via poll(), NIO is epoll. Blocking IO has to copy the array at last once (on the stack for Blocking IO cannot have predictable latency under load at very least, you are left at the mercy of OS thread scheduler. Due to various reasons (e.g. mutator threads should not block GC and compiler ones) thread priorities are honored. I'd argue that a well…
Ok, now I'm curious: what is a good implementation? Also, whats wrong with ByteBuffers? I was under the impression that they are usually memory-mapped and should be 0-copy.
Most impl. use heap ByteBuffer, then parsing requires state machines and often they are simplified by copying the buffers. The blocking IO doesn't really need a state machine as the stack serves that purpose. Then there is some reactive alike pattern (submitting tasks to an ExecutorService) that costs some more latency. Certainly, it's easier to work with and reason about, yet the more hand-outs there are the worse the performance/latency is. There are minor issues like the choice of a good queue. It is an important one as java lacks MultiProducer/SingleConsumer queues out of the box, or even single producer/single consumer. Java does have MP/MC queues (CLQ is an outstanding one) but one has to pay some extra price (incl. false sharing sometimes) to use them.
Ultimately the blocking IO cannot be "faster" than NIO per se since under the hood it uses poll(2)[0] with one socket. Before that it copies the java byte[] to a new location - for smaller byte[] it's the stack. Technically one can blow up the JVM if the stack is very tiny while entering socket.getOutputStream().write(byte[])
Lastly Selector.wakeup() has a stupid issue that involves entering a synchronized block each time even if there is an outstanding wake-up request already. Wakeup requests are implemented via pipes on linux (and a socket pair on Windows) that requires kernel mode switch. During the wakeup all the threads attempting to carry the task block on that very selector for no real reason. It can be played around with a CAS, so only one thread actually enters the monitor.
I will repeat myself blocking IO doesn't have predictable latency and cannot be enforced. In the end it's all about the latency as bandwidth can be bought, more machines deployed but you can't buy latency.
[0]http://linux.die.net/man/2/poll
Some internal stuff on heap vs direct buffer: http://stackoverflow.com/a/11004231
Re: An Opinionated Guide to Modern Java, Part 3: Web Development
#149Earlier quoted context omitted.
That's not what I said, or at least not what I meant. If you have blocking operations (that take a long time), then thread-blocking (as opposed to fiber-blocking or async) IO will require too many threads.
I've heard of Quasar before and had a general idea of what it is, but didn't look at the documentation carefully until now. My understanding is that I can run arbitrary synchronous code in Fibers? For example, consider the MongoDB client library: DBObject r = collection.find(query); It blocks while getting the results of the query. If I do something like this: for (int x=0; x DBObject r = collection.find(query))).sta…
If library provides asynchronous APIs, it would yield great performance when integrated with Quasar fibers. If not (like JDBC), it would work as well as it does on regular threads, but won't interfere with all the other great stuff fibers can do.
Re: An Opinionated Guide to Modern Java, Part 3: Web Development
#150It's great to see how Java web development has progressed. I tried to make a Spring MVC web app work like a decent, modern, readable and productive web application two years ago and it just wasn't possible. Anyone interested in modern JVM web development I would still advise to invest time in learning Scala (or Clojure). They can work with your legacy code and libraries, but my productivity and general joy in program…