Live data from Hacker News

An Opinionated Guide to Modern Java, Part 3: Web Development

blog.paralleluniverse.co

141–150 of 168 posts

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#141
post #83
post #17

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.

I worked with rvb closely last year and we always used to make fun of him whenever this debate came up. Then one day we realized he had co-authored a paper with Eric Brewer on the topic: https://www.usenix.org/legacy/events/hotos03/tech/full_paper...

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#142
post #27

It'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…

> but my productivity and general joy in programming shot through the roof when I started using Scala.

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

#143
post #59

Earlier 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.

Same here, we have multiple large Scala systems, never had issues editing files in IntelliJ.

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#144
post #138
post #135

Earlier 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…

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 another through channels. See: http://blog.paralleluniverse.co/2014/02/20/reactive/

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#145
post #61
post #2

It'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…

Personally I have become quite fond of Ninja Framework ( http://www.ninjaframework.org/ ); as simple as Play, but pure-Java (Java 8 too!). Even has a similar hot-reload mechanism as Play!

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#146
post #116
post #17

You 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…

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.

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#147
post #144
post #138

Earlier 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…

Thanks, this is the kind of answer I was looking for. I'll have a read once I'm on a bigger screen.

Re: An Opinionated Guide to Modern Java, Part 3: Web Development

#148
post #116

Earlier 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.

There are 2+1 major types of ByteBuffers: Heap- backed by byte[] (or char[], int[], etc) Direct: backed by C memory allocated via mmap (on linux). mmap can map to the RAM or a file. Memory mapped files are not an interesting case for NIO impl that works with sockets (On a flip note: FileChannel.transferTo(SocketChannel) doesn't involve memory mapping when the kernel supports it. Windows never supports it, though)

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

#149
post #21

Earlier 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…

The short answer is that you can't just use any blocking code. The Comsat project (https://github.com/puniverse/comsat) contains integrations of popular libraries with Quasar fibers, without change to their API. Under the hood, this is done using transformations made available in the FiberAsync class. Like eitany said, you can use FiberAsync to integrate the library yourself, or wait for an integration module in Comsat.

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

#150
post #27

It'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…

You can actually make a good Spring MVC-based webapp (with Thymeleaf, AngularJS and etc.); check out the JHipster Yeoman generator: https://jhipster.github.io/
Post reply on HN