Hacker Newsnew | past | comments | ask | show | jobs | submit | pseudoramble's commentslogin

I’ve been out of the Java scene for a really long time, but will be coming back to it soon. I’m curious - these performance issues described here, are they inherit to how Java itself? Is it baggage from Spring/Boot? Are there ways to get more bang for the buck with some careful choices in a system like this?

The closest I’ve done to Java recently is C#, which I think may have similar challenges, but overall didn’t seem quite as bad if you avoided lots of framework extras. It also wasn’t something I was digging into deeply though, so perhaps I’m mistaken.


You can write clean beautiful Java and make it perform beautifully if you're careful with what you pull in for dependencies... but then you're not really using Java to its full potential as an ecosystem for basically building massive line of business apps and services that you can spin up everything from junior to offshore to 30 years of experience developers. The tradeoff for this is performance and it's a thing a lot of companies are willing to trade off on.

Things get messy the moment you involve large frameworks, reflection, ten different approaches to parallelism etc. There's also the problem of code base evolution in Java. Code before JDK-8 feels different than code after it and there's a lot of Pre-JDK 8 code out there in the wild.

And that's just it at the end of the day... it's a cultural difference in the ecosystems.


My experience with very simple Jersey web apps is ~1.5 seconds to start up. Much less than his reported ~8 seconds with Spring Boot, but still not in the 100 ms range he reports with Go. I assume one second or so is about as low as you can go with a mainstream Java framework without AOT, though I'd be happy to be corrected.


I worked on an app in kotlin a while back, and am currently working in a dotnet app. We can run our entire unit test suite faster than the JVM started up on that project.

Also, 8 seconds is quick in my experience for Java - I’ve seen more like 15-30


The JVM starts in milliseconds

Probably you're loading many thousands of classes...


It certainly tells me it does. i can hit 'run unit test', sit back in my chair and zone out for 5 seconds, then come back and read that the test took 22ms.


Thanks for bringing up some painful memories. Now I'm working in C and tests take about 100ms end-to-end (multicore, no frameworks). Sometimes I re-run them for no reason just to enjoy how fast everything is.


haha well your test did take 22ms, but starting the JVM and loading all the classes and all your dependency injection stuff probably took 5s. You can test it yourself with a tiny hello world, it's pretty fast to start.


But that's our point - you're saying java is fast (and it is ripping fast once it gets going) and the startup is fast, unless it's not.


Well no, startup is fast, period. You're probably just giving the class loader a ton of work on startup? I would start with checking that I think.

It could also be when he's hitting "run test" it's actually "compile and run"...


> Well no, startup is fast, period. You're probably just giving the class loader a ton of work on startup? I would start with checking that I think.

Ok, maybe I misspoke about the "JVM" startup. But the time between `mvn test` and it actually logging the first line of user code was in the region of 15 seconds. Every java project I've worked on has had startup time issues once they're bigger than a toy project.

Saying "the JVm startup is fine, it's just the class loader that's slow" reinforces the point of "it's slow to startup"

> It could also be when he's hitting "run test" it's actually "compile and run"...

This would be true in C# too, and in go. Both of those tools have much quicker compilation times IME than java, which is just a nice plus.


BTW, I wonder if any test frameworks are using the hot reloading JVMs yet? Would also solve this problem.


That's mostly because nobody cares enough to optimize it, but if you split code into modules so your number of classes, including dependencies, is smaller, then your tests will start quickly. Usually it's dependencies and DI that's the cause of this I think.

Aren't Go's compile times about the same as Java's? Of course it depends on what tooling you use to package the jars.


Well I could switch to a programming language that isn't so slowed down by ahead-of-time compilation. Maybe a JIT language?


Yeah that’s been my experience too.


Can confirm with Vert.x. I used to have a JRebel subscription for code hot swapping in another project but in my current Vert.x thing I simply don’t need it. It’s just fast.


Also, you don't have to continuously restart the server for every change. Can hot swap code. And for tests there are solutions to keep the jvm running between the code->test->fix cycle. But I've never felt the need for those, running a single test is often plenty fast as one doesn't need to instantiate the whole app, only the dependencies needed for the test. So plenty fast.


Spring by far - Spring is effectively a build tool running at run time (scanning, enhance, code generation, etc.) - most of it is just startup as JVM does a decent job at optimizing the cruft. In most cases the boot times don't matter, though - at least for most people, esp. when it comes to production. (it's mostly developers time wasted)

I have some personal experience optimizing Spring to record previous runs and effectively cache resolution and code generation, etc. for massive boot latency improvements. Never got around contributing it back, though (not a real spring user)


> most of it is just startup

Yep, I have some Spring code in AWS ECS and it hits 100% CPU usage on start-up before dropping back to 1.5% when idling (this is with 1 vCPU I think).

But yeah I remember reading one of the Spring devs say that some (a lot?) of the runtime reflection could be done at compile time but isn't.


> Spring devs say that some (a lot?) of the runtime reflection

It's a lot more than reflection, if it'd have been reflection alone - it'd be markedly better. (and yes, lots and lots can be optimized). Spring effectively:

  scans the classpath for resources - that includes jars, file system
  loads every single class matching the scanned directories as a byte array
  parses it in java (not by JVM) to check what annotations it has (it doesn't load  the classes actually)
  builds dependency tree
  enhances the previously loaded byte arrays, i.e. generates different byte code
  loads the newly enhanced classes and create instances (usually through standard reflection)
  makes calls like PostInit (life cycle)
  in some cases it uses the standard java reflection to set fields/call methods; in lots of cases java reflection is generating (and loading) a new class (byte code) to carry the process
all the steps above can be recorded on run time (or be a step in the build process) and let the JVM just load the classes organically.

as for the 100%, spring initialization is mostly single threaded - so likely you dont have many cpus dedicated to the java process. (or you meant just a single core 100%)


Ah okay - yeah I'm not across the internals at all.

And yeah I assume it's a single core, but definitely a heavy start.


This makes recycling nodes, be it ECS or Kubernetes nodes, that run tons of Spring apps, a huge pain.


In my experience, if you write Java like you'd write to, you'd probably get similar performance. Maybe AOT performs a bit better, maybe it doesn't because it disables live optimizations.

Java doesn't lend itself well to writing Go style code, though. You quickly end up writing very "Java" Java code. That has some advantages (code deduplication, less boilerplate) but also downsides (allocation overhead, performance impacts).

In terms of Java vs C#, I don't think you'll notice too many new issues. If you opt into using heavy frameworks like Spring Boot to solve annoying problems for you, you'll see RAM usage increase massively, but it'll also take care of a lot of annoying grunt work for you. Startup times overall are pretty similar. The biggest downside in my experience is the lack of nullable types (@Nullable annotations are a poor substitute) and some syntax improvements that are new to Java but have been part of stable C# for many years.

As long as you stick with small libraries and avoid writing too much ObjectInjectorFactoryProducerResolver style code, performance of the JVM is fine.

All of that goes as long as you're able to use modern toolkits. If you're stuck in the world of Enterprise Java with Oracle Java 8, you'll notice old Java's shortcomings a lot more.


You can do AOT compilation with GraalVM to reduce both startup times and memory usage, but then you don't have the JIT.


I think this upcoming feature will let you have both AOT + JIT without needing GraalVM: https://wiki.openjdk.org/display/crac


Having done a lot of Java and Go, Go has much better mechanical sympathy between the language, libraries, and vm than Java does. The JIT GC in Java are marvels of engineering, but they have to be.

As an example, in Java, everything is a pointer, so pointer chasing all the time, which is not good for cpu cache, etc. In Go, there is first class support for composition.

The other main adjustment, if coming from Java, is reduced cognitive overhead. It usually only takes a week or two for an experienced Java dev to be reasonably effective in Go, but it takes a few months to break the mental habits of overthinking everything.


> As an example, in Java, everything is a pointer, so pointer chasing all the time, which is not good for cpu cache, etc

Strictly speaking that's not true. It's everything is a pointer in theory to make it easier to reason with and JIT / JVM optimizing in the background.

There are primitive types and there are lots of tricks in the JVM e.g. escape analysis that places objects on the heap/stack etc.


Despite all the advances in JIT, I've literally never seen it correctly optimize a HashMap<Integer> (happy to be proven wrong). Hopefully the renewed focus on value types can finally bring some sanity.


In C#, all struct generics are monomorphized and struct-based abstractions are zero-cost :)


There's nothing forcing you to write EE style code in Java though, or depend on frameworks written in that style.


This is actually a really cool feature. I've never had any interest in an Apple Watch, but this is something I'd be genuinely interested in. Too bad it requires an iPhone largely.

I think there are other less time intensive methods outside of a sleep study, but it is nice to simplify it down to just wearing this and finding out!


This context helps me understand more what you're getting at quite a bit. I dunno if I could manage the same approach but I at least appreciate how you're thinking about it. Thanks!


> Another issue is that in your mid 30's almost everyone has settled down and started having kids and only really prefer socializing with other people who have settled down and have kids, leaving you in an awkward place.

To add a bit of a different perspective to this, as a parent myself, most of our friend groups are actually child-less and have no plans to have children. I've found it works quite well. They are cool with or genuinely excited to hang out with the kids, and this affords them a way without the full obligation of parenthood. The friend relationship evolves when you have kids, but with the right kinds of people and interest, it evolves in a great way I feel.

Of course I'm just part of one family, which is a small sample size. So perhaps you're onto the real trend. But I do feel it important to say that there's room in this world for folks with or without kids. It doesn't have to be mutually exclusive!


Not too interested into diving into the debate itself, but one minor point I wanted to add to the article where they count the commits to squash and then do `git rebase -i HEAD~n` is that you can replace this strategy with using the branch you're targeting. So if you're working on a feature branch to merge into `main` you can update the local main branch first, then punch in `git rebase -i main` and it'll handle finding all the commits for you.

I'm sure there's even more clever ways to do this, as it always seems like there's more when it comes to git. This is just the most intuitive way I've seen so far, and so it sticks in my mind.


And a fairly quick way to do the same sort of thing is `git fetch && git rebase -i origin/main`. You never bother updating `main` because you kind of don't care for the task at hand.


True, good point. Makes sense! Thanks for the improvement!


There is offering from the creators of Peertube I believe: https://sepiasearch.org/. I think instances have to be added manually into the index, and tbh I don't use it much and so I'm not sure of the quality. But it sort of covers what you're asking for, at least kinda.


Sorry I'm unaware of what you're saying? Are you saying that pilots are being selected without meeting training requirements and licensing? That doesn't sound right and I must be missing your point.


I think, reading between the lines, you are replying to a "blame wokeness for everything bad that happens" post. Being generous, it's about one order of magnitude more rational than blaming gays for earthquakes. But it's the same basic idea.


This is a bit tangential, but, have middle managers ever actually had those powers? I mean this in a genuine way. My post college career began in 2011, and all I've known is hopeful managers who aren't empowered to do much of anything like just decide to hire a person, give somebody a raise, or make major changes to company strategy or anything. Is that one of those things that really did exists like offices with closing doors and other things?


It's a fair question. To be fair, I entered my field post pharmacy school in 2013 and was immediately place in a middle manager position. The "old dogs" spoke a lot about the days of old in which they did have a lot of power and flexibility. I've since moved up in another company into a national VP level position and I hear the same from older VPs, they used to have more power and flexibility. So anecdotally, I think there has been a lot of consolidation and power hoarding in high level executive positions.


> have middle managers ever actually had those powers?

Oh, yes, I've had many managers who were empowered over the last 35+ years. I have one right now. But how true this is depends on the company culture.

I doubt that I'd stick around long at a company that wasn't like this. I'd leave on the basis of the company having poor management.


Yeah the behavior was completely counter intuitive to what I was expecting. It does make sense though since it would be kinda weird if an HTML attribute could change the structure of mark up directly, at least I realized that after thinking about it.


Cool! Looking through this made me curious - how do people tend to translate between languages? For example, do people tend to know English and then translate it to that language? Or do people find a good translation they know to reference for another language? Or maybe translate into an intermediate language that's closer to a target language, then translate to the target language? I've never really heard about what people's processes tend to be, and I only know English. So I don't have a clue!


My native language is Greek but I have been involved in translating stuff from English to Greek before.

Most translators in open-source projects are pretty familiar with English. Usually they have a technological or background so English is a must. Often we struggle with translating terms into our very own language because at least in some cases they may sound a bit weird.

I personally tend to use English UIs in the software I use because it reduces the cognitive load off trying to figure out the exact term at hand, but for my 85yo mom that struggles with very basic stuff yeah I'm glad she has the choice to use Greek.


Yeah that makes sense. Definitely vital to have your language of choice when possible!


Consider applying for YC's Fall 2025 batch! Applications are open till Aug 4

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

Search: