Foundation Laid for Faster Text I/O

Hey guys! How’s it going?

Another six months are over and you might wonder what the old shaggy prepared this time? πŸ€” No wonder, it certainly is another OpenJDK contribution! 🀩 This time, it speeds up reading from CharSequence, and it will allow faster Write::append. πŸ‘

Never heard of CharSequence? Well, it’s the common interface of String, StringBuilder, CharBuffer, and quite some custom classes out there. But wait! There are other text classes than String? 😯 Maybe you never thought abot that… 🀨 And why would you want to speed that up? Because a program never is fast enough, but more urgently, because it reduces power consumption! So, once more, we gain fun from faster apps, plus saving the climate. 🌴 Ain’t that great? So read on!

So for long time, you did not think about what happens “under the hood” when you concatenated Strings, like "abc" + "def". But then someone came and told you not to do “+” but use StringBuild::append, as that would be way faster (which it was). And then someone else came and told you, that this is an urban legend, as javac meanwhile does exactly that for you (which it does). But in fact, what happens still is that (directly or indirectly) memory is allocated which is the size of "abc" plus the size of "def" (even worse, it is not even stack memory but heap memory, but let’s put that aside for today). Actually, there is even more work done: As Strings are compressed internally, an compression algorithm chimes in. And yes, that needs time and memory, and energy, too. πŸ˜“ Indeed there is even more going on internally, but more or less we could say: Concatinating Strings is effectively making a compressed copy, then throwing away both original values, even in the Java 25 age. And “throwing away” means, leaving behind holes in the linear memory space. So besides pure Garbage Collection (“vacuuming”), we need memory defragmentation (“waste grinding”), which is another nice word for: moving even more bytes around in memory. And that costs even more time and power. And guess what: Your app concatenates Strings a lot, right? And guess what: The Java Runtime (JRE) itself internally concatenates even more Strings! So copy, reallocate, compress, deallocate, GC, defrag all the time. But for what? For nothing! πŸ˜” Sigh.

For nothing? Yes, for nothing. Because you could spare a lot of that – when further using StringBuilder instead of String. Ok, you know that since long time, so you do that, and so is javac (it replaces String+String by a StringBuilder “under good conditions”), and so is the JRE itself. But here comes the bad news: In the end, you, just like javac, just like the JRE itself, are calling toString() eventually. Don’t you? You do! And that means… right: Pointless power consumption, as toString() produces another temporary copy on the heap!

So why not omitting toString()? Just directly pass around your StringBuilder everywhere, instead of toString()’ing it! This spares lots of toString(). (cheer) So all is fine now? Nope. (cheer stops). Once you want to output your StringBuilder, or once you want to input text into a StringBuilder, you’re facing a problem: Your surrounding frameworks do not accept StringBuilder! Typically these all work with String, or, like in the case we’re talking about today (to finally come to the copic of today’s posting), they do accept CharSequence – but they internally toString() it. πŸ˜’

For example: Java’s Writer classes (you know, like good old BufferedWriter, PrintWriter, and all those) just pretend to accept not only Strings (like in write(String)), but also any other kind of CharSequence (like in append(myStringBuilder)). That looks just as what we want to spare that toString() heap clutter. But wait! 🫷 Take a look at the implementation first… it does… tada… toString()! πŸ₯³ So that nice trick that javac internally uses a StringBuilder to implement “+” is good for nothing, as finally you end up with another time-squandering copy as soon as you output the result. 😭

But stopy crying! I am here to help! 🦸 The other day Oracle kindly adopted my latest OpenJDK contribution, and this finally paves the way to fix these troubles. To understand my solution, let’s dive deeper into Writer, and why it does toString() on any CharSequence (even on Strings themselves). The cause is: Performance. Shocking! 🫒 If you copy text “char-by-char” this would be totally slow, as computers can pass around much larger clusters of information with a single command. So what Writer::write internally does is, it asks the String to put all its characters into a char array with a single command (which ontop is lightning-fast machine code ⚑). That command is String::getChars(int, int, char[], int). So why doing that only with Strings, but not with other CharSequences? Because CharSequence does not have that command. It’s as embarrasing as that! CharSequence only can be asked for one character at a time, so you need a loop in Java – which means, in 99% of you cases, an interpreted loop (unless you do it 10.000 times to get it hot spotted eventually). And that is not just slow, it is even super-slow! 🐌

So what I did is that I added that exact getChars(int, int, char[], int) method signature that String always had to the CharSequence interface. Sounds easy, but took six months of discussions and a lot of convincing (for example, I had to proof that “not many” code exists on earth that already has such a method but that method does something else – as that code would silently do the wrong thing once executed on Java 25). This foundational change is now found in Java 25, and if you download a pre-release build, you can play with it right now – or already prepare your application if it does a “char-by-char” loop or temporary toString() currently.

So what about Writer? I’m working on it. Just today I filed the first of a set of pull requests towards getting this new method used in all Writers in OpenJDK. So while nothing will get faster “magically” in JDK 25, the foundation is laid, and by the time, eventually your code runs more efficient, without recompiling it. So… stay tuned…! πŸ˜…

Posted in Allgemein | Tagged , | Comments Off on Foundation Laid for Faster Text I/O

Reader.of(CharSequence)

Hi guys, how’s it going? Long time no see! πŸ˜…

In fact, I had been very silent in the past months, and as you could imagine, it has a reason: I just had no time to share all the great stuff with you that I was involved with recently. In particular, creating video content for Youtube is such time-consuming that I decided to stop with that by end of 2023, at least “for some time”, until my personal stress level is “normalized” again. Unfortunately, now by end of 2024, it still is at 250%… Anyways!

Having said that, I decided to restart my blog. While many people told me that blogging is @depreceated since the invention of VLogs, I need to say, it is just so much easier for me to write a blog article, that I decided to ignore them and write some lines about my latest Open Source contribution. So here it is: My first blog entry in years!

But enough about me. What I actually wanted to tell you today is that I am totally happy these days. The reason is that since this week, JDK 24 EA b22 is available for download, and as you can see in the preliminary JavaDocs, my very first addition to the official Java API is contained: Reader.of(CharSequence) πŸš€!

You might wonder what’s so crazy about that, because (as you certainly know) I am a contributor to OpenJDK since many years. Well, yes, I did contribute to OpenJDK (alias “to Java”) for long time, but all my contributions where just “under the hood”. I have optimized execution performance, I improved JavaDocs, I added unit tests, and I refactored code. But this time, I added a complete new feature to the public API. It really feels so amazing to see that my work of the past few weeks now will help Java developers in their future projects to spare some microseconds and some kilobytes per call, and in sum, those approx. ten million developers (according to Oracle marketing) will sum up to considerable amounts of CO2 that my invention will spare! 🌞🌍🌴

Okay, so what actually is Reader.of(CharSequence) all about, how can you use it, and how does it spare resources?

I think you all know what the class StringReader is, and what to use it for: You need (for whatever reason) an implementation of the Reader interface, and the source is a String. At least that what it was made for decades ago. In fact, looking at the actual uses in 2024, more often than not the source isn’t a String actually, but is (mostly for performance reasons) a StringBuilder or StringBuffer, and sometimes (mostly for technical reasons) a CharBuffer. These classes all share one common interface, CharSequence, which is “the” interface of the class String, too. Unfortunately, StringReader is unable to accept CharSequence; it only accepts String. That’s too bad, because it means, most uses of StringReader actually perform an intermediate toString() operation, which creates a temporary copy of the full content on the heap – just to throw it away later! 🀦Creating this copy is anything but free! It imposes time to search a free place on the heap, to copy the content onto the heap, and to lateron GC (dispose and defragment) the otherwise unused copy in turn. Time is not just money – This operation costs power, and power costs (even these days) CO2! πŸ™

Ontop of that, most (possibly all) uses of StringReader are single-threaded. I investigated for some time but could find not a single reason for accessing a StringReader in a multi-threaded fashion. Unfortunately, StringReader is thread-safe: It internally uses the synchronized keyword in every single method. Each time. For each single read in possibly a loop of thousand iterations! And yes, you guess right: synchronized a everything by fast. It slows down code considerably, for zero benefit! And: No, the JVM has no a trick to speed this up in the single-threaded use cases – that trick (“Biased Locking”) went away years ago and the result is that synchronized is slow again! πŸ™

Imagine you are writing a RESTful web server which returns JSON on GET. JSON is nothing else but a character sequence. You build it from a non-trivial algorithm using a StringBuilder. That particular JSON unfortunately is non-cachable, as it contains information sent with the request or changing over time or provided by the real physical world. So the server possibly produces tens of thousands of StringBuilders per second and reads it using a StringReader. Could you imagine what happens to your performance? Thanks to the combination of both effects described earlier, you’re losing money with every other customer contacting your server. YOUR money, BTW.

This is exactly what happend in my latest commercial project, so I tried to get rid of StringReader. My first idea was to use Apache IO’s CharSequenceReader, which looks a bit old-school, but immediately got me rid of both effects instantly! πŸ‘ The problem with Apache IO is that it is rather huge. Using lots of KBs of transitive dependencies just for one single use case didn’t sound like a smart option (but yes, this is the code actually in production still – at least unless JDK 24 is published in Q1/25). Also, the customer was not very pleased to adopt another third-party library into the game. And finally, the code of Apache IO is not really eagerly maintained; they do bug fixes, but they abstain from using modern Java APIs (not even using multi-release JARs). Some will hate me for writing this, but the actual change rate didn’t look like “stable”, it looked to “dead” – agreed, this is subject to my personal interpretation. πŸ₯΄

Being an enthusiastic Open Source committer since decades, and being an OpenJDK contributor since years, I had the idea to tackle the problem at its root: StringReader. So I proposed to provide a PR for a new public API, which was very much appreciated by the OpenJDK team. It was Alan Bateman himself (Group Lead of JDK Core Libraries) who came up with the proposal to have a static factory, which culminated in me posting a PR on Github about adding Reader.of(CharSequence). After accepting the mandatory CSR it recently got merged, and since JDK 24’s Eary Access Build 22 it is publicly available. πŸš€

BTW, look at the implementation of that Reader’s bulk-read method. There is an ugly sequence of tricks to speed up performance. I will address this in a subsequent upcoming PR. Stay tuned!

So if you want to gain the performance benefit, here is what you need to do:

  • Run your app on Java 24 EA b22+.
  • Replace all occurances of new StringReader(x) and new CharSequenceReader(x) by Reader.of(x).
  • If x ends with .toString() then remove that trailing .toString() – unless the left side of x is effectively not a CharSequence.
  • Note: If you actually use multiple threads to access the Reader, don’t stick with StringReader, but simply surround your calls by a modern means of synchronization, like a Lock – locks are faster than synchronized.

Please exterminate StringReader but adopt Reader.of() ASAP!

I would be happy if you could report the results. Just leave a comment!

So far for today! PARTY ON! 🀘

Posted in Java, Open Source, openjdk, Programming, Projects | Tagged , , , , | Comments Off on Reader.of(CharSequence)

Coding Microservice From Scratch (Part 16) | JAX-RS Done Right! | Head Crashing Informatics 83

Write a pure-Java microservice from scratch, without an application server nor any third party frameworks, tools, or IDE plugins — Just using JDK, Maven and JAX-RS aka Jakarta REST 3.1. This video series shows you the essential steps!

You asked, why I am not simply using the Jakarta EE 10 Core API. There are many answers in this video!

If you like this video, please give it a thumbs up, share it, subscribe to my channel, or become my patreon https://www.patreon.com/mkarg. Thanks! πŸ™‚

Posted in Jakarta EE, Java, Lectures, Microsoft, Programming | Tagged , , , , , | Comments Off on Coding Microservice From Scratch (Part 16) | JAX-RS Done Right! | Head Crashing Informatics 83

Jersey Performance Improvement (Step One) | Code Review | Head Crashing Informatics 82

Let’s take a deep dive into the source code of #Jersey (the heart of GlassFish, Payara and Helidon) to learn how we can make our own I/O code run faster on modern Java.

In this first step, we apply NIO APIs from #Java 7 and 8 to process data more efficiently, and most notably: outside of the JVM.

If you like this video, please give it a thumbs up, share it, subscribe to my channel, or become my patreon https://www.patreon.com/mkarg. Thanks! πŸ™‚

Posted in Java, Open Source, Programming, Projects, The Two Minutes Tuesday | Tagged , , , , , , | Comments Off on Jersey Performance Improvement (Step One) | Code Review | Head Crashing Informatics 82

Jersey powered by NIO | The Two Minutes Tuesday 041 | Open Source

Thanks to my latest contribution, #Jersey now runs on #NIO – and is considerably more efficent. πŸš€ #performance #java

If you like this video, please give it a thumbs up, share it, subscribe to my channel, or become my patreon https://www.patreon.com/mkarg. Thanks! πŸ™‚

Posted in Java, Open Source, Programming, Projects, The Two Minutes Tuesday | Tagged , , , , , , | Comments Off on Jersey powered by NIO | The Two Minutes Tuesday 041 | Open Source

Now I am JCommander committer | The Two Minutes Tuesday 040 | Open Source

Since few weeks I am committer and release manager of JCommander. πŸš€

If you like this video, please give it a thumbs up, share it, subscribe to my channel, or become my patreon https://www.patreon.com/mkarg. Thanks! πŸ™‚

Posted in Java, Open Source, Programming, Projects, The Two Minutes Tuesday | Tagged , , , , , | Comments Off on Now I am JCommander committer | The Two Minutes Tuesday 040 | Open Source

Contributing to OpenJDK | The Two Minutes Tuesday 039 | Open Source

I really adore to be part of #OpenJDK! πŸ˜ƒ

If you like this video, please give it a thumbs up, share it, subscribe to my channel, or become my patreon https://www.patreon.com/mkarg. Thanks! πŸ™‚

Posted in Java, Open Source, Programming, Projects, The Two Minutes Tuesday | Tagged , , , , , | Comments Off on Contributing to OpenJDK | The Two Minutes Tuesday 039 | Open Source

Welcome to the Liquibase Community | The Two Minutes Tuesday 038 | Open Source

I have fixed a lot of bugs in Liquibase, but it was worth it!

If you like this video, please give it a thumbs up, share it, subscribe to my channel, or become my patreon https://www.patreon.com/mkarg. Thanks! πŸ™‚

Posted in Java, Open Source, Programming, Projects, The Two Minutes Tuesday | Tagged , , , , | Comments Off on Welcome to the Liquibase Community | The Two Minutes Tuesday 038 | Open Source

No videos for long time! | The Two Minutes Tuesday 037 | Announcement

I feel very bad for letting you wait so long for new videos. But more open source stuff is in the queue!

If you like this video, please give it a thumbs up, share it, subscribe to my channel, or become my patreon https://www.patreon.com/mkarg. Thanks! πŸ™‚

Posted in Java, Open Source, Programming, Projects, The Two Minutes Tuesday | Tagged , , , , | Comments Off on No videos for long time! | The Two Minutes Tuesday 037 | Announcement

JCommander 1.83

Some weeks ago CΓ©dric BEUST (the founder of JCommander, TestNG and GMail on Android) granted committer status to me, and appointed me as the release manager of JCommander. The first means, I can push commits into the Github repo. The second means, I can push releases into Maven Central. CΓ©dric and me think this is the right move towards more frequent releases, and a more agile community, in the sense of “release early, release often”.

As my first official task I feel proud and honoured to announce that I have published JCommander 1.83 earlier this week.

Noticeable changes are the fact that you need to use the Maven Group ID org.jcommander from now on, and that this release contains an new feature: By implementing the new IParametersValidator interface you can write validation code that considers interdependent sets of options, so for example, when you need to ensure that –verbose is not used together with –quiet etc. Check out the recently updated online docs for more information about Global Parameter Validation. There is also a video about this feature on my Youtube channel.

Do you miss a feature in JCommander? Just drop me a note and I will consider implementing it!

Posted in Java, Open Source, Programming, Projects | Tagged , | Comments Off on JCommander 1.83