
An internal Apple developer team revealed in a new case study that “Java’s memory management approach no longer aligns with our growing demands and efficiency goals.”
The team is now looking for more efficient languages, and in this example chose Swift, achieving a claimed 50 percent reduction in hardware utilization, 90 percent less memory, and 40 percent more throughput.
The service is for password monitoring, checking user passwords against a list of those that have leaked. The application receives “multiple billions of requests per day from devices all over the world,” according to the post from the development team. The service runs on Linux and includes layered encryption which increases the compute resource needed for each request.
“For years, our team relied on Java to power large-scale, mission-critical services because of its proven stability and performance,” said the developers, but nonetheless decided to look for another language because of issues with garbage collection. Garbage collection (GC) is a technique for managing memory automatically, by freeing memory that is no longer required in regular sweeps, but despite improvements in Java’s GC there were still issues with GC pauses under load and its performance overhead.
Scaling is another issue. The service load varies substantially during the day and Apple scales the hardware in use accordingly. When firing up new hardware on demand, boot time becomes critical, and managed languages like Java tend to take longer because of their greater runtime requirements – a problem AWS has worked on with its SnapStart technology.
The team chose to rewrite the service in Swift, developed by Apple as a modern alternative to Objective-C. The web framework used was the open source Vapor. Swift also has automatic memory management, but unlike Java it is implemented with ARC (automatic reference counting). The pros and cons of ARC versus other approaches to GC are debated; but in this case the team found substantial improvements, including a 90 percent reduction in memory usage as well as half the hardware utilization, for a service running on Kubernetes.
It is possible that another aspect of the port, a near 85 percent reduction in lines of code, was more significant than the memory management. The team identified aspects of Swift which resulted in cleaner and more concise code, including an emphasis on protocols (interfaces) rather than inheritance, the use of async and await for concurrency, and type safety which eliminates the need for null checks.
Is Swift more efficient than Java, or was the rewrite simply coded better? It is likely that both are true. Swift compiles to native code and has no need for a JVM (Java Virtual Machine) or JIT (just-in-time) compiler.
Apple has its own reasons for promoting Swift; and although the team hinted that Swift was not its automatic choice after deciding to drop Java, one cannot discount the internal pressure. A migration to Go (the language used to code Kubernetes) would likely offer similar improvement, as would Rust.
Java is celebrating its 30th anniversary, and rightly praised for its productivity and reliability. That said, and it may spoil the party a little, it is worth noting that a port to a more efficient language can yield such substantial improvements and savings.