JEDI: Java Evaluation of Declarative and Imperative Queries
This paper presents JEDI, an automatically generated benchmark suite that converts SQL queries into Java to evaluate and compare the performance of declarative Stream API implementations against imperative baselines, aiming to identify inefficient code patterns and guide the optimization of the Java Stream API.
Original paper licensed under CC BY 4.0 (http://creativecommons.org/licenses/by/4.0/). This is an AI-generated explanation of the paper below. It is not written or endorsed by the authors. For technical accuracy, refer to the original paper. Read full disclaimer
Imagine you have a massive warehouse full of boxes (data), and you need to find specific items, sort them, and count them. You have two ways to give instructions to your workers:
- The "Manager" Approach (Imperative): You walk up to each worker individually and say, "Pick up this box. Check if it's red. If yes, put it in a pile. If no, throw it away. Now pick up the next one." This is very direct and fast, but it requires a lot of talking and can get messy if you have thousands of workers.
- The "Foreman" Approach (Java Stream API): You write a single, elegant note: "Take all boxes, filter for red ones, sort them by size, and count them." You hand this note to a foreman who figures out how to get the workers to do it. This is much easier for you to write and read, but the foreman has to translate your note into actions, which sometimes takes extra time.
This paper, titled JEDI, is all about testing how well the "Foreman" (the Java Stream API) performs compared to the "Manager" (traditional code), and figuring out how to make the Foreman work faster.
The Problem
The Java Stream API is popular because it makes code look clean and easy to understand (like the note to the foreman). However, developers have suspected that this "clean" way of writing code is slower than the "messy" traditional way. The problem is, no one had a proper race track (a benchmark) to test this fairly. Without a race track, the people who build the Java language (the "mechanics") don't know exactly where the engine is sputtering, and developers don't know which instructions give the best speed.
The Solution: JEDI
The authors built JEDI (Java Evaluation of Declarative and Imperative Queries). Think of JEDI as a giant, automated factory that takes standard database questions (written in a language called SQL, which is like a universal request form) and instantly translates them into two different sets of instructions:
- One set using the "Foreman" style (Streams).
- One set using the "Manager" style (Imperative loops).
Because the factory translates the exact same question into both styles, the comparison is perfectly fair. It's like giving two runners the exact same path and timing them to see who is faster.
What They Discovered
1. Small Tweaks Make a Big Difference (The "Filter Fusion")
Sometimes, the Foreman gets confused if you give him three separate notes: "Check for red," "Check for big," "Check for heavy."
- The Fix: The authors found that combining these into one big note ("Check for red AND big AND heavy") makes the Foreman much faster. It's like giving a worker one clear instruction instead of three confusing ones.
- The Result: This simple change made the code run up to 2.6 times faster in some cases.
2. The "One-to-Many" Trick
Sometimes a single box contains many smaller items inside.
- The Old Way: The Foreman would take the box, open it, pull out one item, put it in a pile, go back, pull out the next, and repeat.
- The New Way: The authors found a special tool (called
mapMulti) that lets the Foreman open the box and dump all the items out at once in one smooth motion. - The Result: This was even more effective than the first tip, often doubling the speed.
3. The Parallelism Puzzle (Using Many Workers)
When you have a huge warehouse, you want to use many workers at once (parallel processing). The paper tested four different ways to organize these workers:
- The "Strict Order" Team: Everyone works in a line, passing boxes down. Good for keeping order, but slow.
- The "Chaos" Team: Everyone grabs boxes randomly. Fast, but hard to manage.
- The "Shared Board" Team: Everyone writes their results on one giant shared whiteboard.
- The "Atomic" Team: Everyone uses a special, high-tech pen that never smudges, even if two people write at the same time.
The Verdict: There is no single "best" team.
- If you have very few groups of items to sort (like sorting only 4 types of fruit), the "Strict Order" or "Chaos" teams are fastest because the "Shared Board" gets too crowded (too much arguing over who writes first).
- If you have thousands of groups (like sorting 10,000 different fruit types), the "Shared Board" team wins because the arguing stops, and everyone can write their own section without bumping into others.
4. The Speed Gap
The big question: Is the "Foreman" (Stream) slower than the "Manager" (Imperative)?
- Yes. The traditional "Manager" code is consistently faster, usually by about 30% to 40%.
- Why? The "Foreman" has to spend time translating your elegant note into actions. The "Manager" just does the work immediately.
- The Good News: The gap isn't as huge as people thought it might be in the past. The Java team has been improving the engine. However, for the absolute fastest performance, the "Manager" style still wins.
5. The Trade-off: Speed vs. Sanity
The paper also looked at how hard the code is to read.
- The "Manager" code (fastest) is like a dense, confusing instruction manual. It's hard to read and easy to make mistakes in.
- The "Foreman" code (slower) is like a clear, short story. It's much easier to understand and less likely to have errors.
- The Lesson: You have to choose. Do you want the code to run 30% faster, or do you want it to be 2.5 times easier for humans to read and maintain? The paper suggests that for most people, the "Foreman" style is worth the small speed penalty because it saves time on debugging and maintenance.
Summary
JEDI is a new tool that helps developers understand the "cost" of using the modern, easy-to-read Java Stream API. It proves that while the easy-to-read code is slightly slower than the old-school code, you can make it much faster by using specific tricks (like combining filters). It also tells developers exactly how to organize their workers (parallel strategies) depending on how much data they have. Ultimately, it gives developers a roadmap to write code that is both readable and reasonably fast.
Drowning in papers in your field?
Get daily digests of the most novel papers matching your research keywords — with technical summaries, in your language.