Using Project Loom to improve multithreading performance in Java

Tram Ho

1. Introduction

In an era of ever-evolving technology, the demand for performance and scalability of software applications is increasing day by day. Multithreading is a popular method of improving application performance and scalability. However, traditional multi-threaded programming in Java still has many limitations and challenges. To solve these problems, the Project Loom project was born with the aim of providing a new approach, making it easier to improve multithreading performance in Java. In this article, we will learn about Project Loom – a promising Java project, the problems and limitations of traditional multi-threaded programming, the working mechanism of Project Loom, the advantages of using Using Project Loom versus traditional multi-threaded programming, how to integrate Project Loom into an existing Java project, performance evaluation, and ultimately the future of Project Loom and its impact on the Java developer community .

2. Multithreading in Java and current issues

2.1. The concept of multithreading

Multithreading is a programming technique that allows multiple threads to execute concurrently in the same application. Each thread is an independent unit of execution, capable of running in parallel with other threads. In Java, multithreading is supported through the Thread class and the Runnable interface. Programmers can create new threads by either extending the Thread class or implementing the Runnable interface.

2.2. Problems and limitations of traditional multithreaded programming

  • Performance: As the number of threads increases, the performance of the application does not increase linearly. This is because threads have to share hardware resources, and managing and scheduling threads also costs CPU time. This leads to an increase in the number of threads that does not equate to a significant performance increase.
  • Scalability: In complex applications, managing a large number of threads makes it difficult to ensure scalability. Synchronization issues, limited resources, and deadlocks can occur, making the application difficult to develop and maintain.
  • Code complexity: Multi-threaded programming requires programmers to deal with many problems related to synchronization, avoid resource conflicts, and solve deadlock problems. This increases the complexity of the source code and makes it difficult to maintain and extend the application. Realizing the limitations of traditional multi-threaded programming in Java, the Project Loom project was born to solve the above problems and provide a more efficient multi-threaded solution.

3. Project Loom’s mechanism of action

Project Loom introduces a number of new enhancements and constructs to help simplify multithreaded programming and improve the performance of Java applications. The main components of Project Loom include Virtual Threads (Fibers) and Continuations.

3.1. Virtual Threads (Fibers)

Virtual Threads, also known as Fibers, is a new concept that reduces complexity and increases performance of multithreaded programming. Virtual Threads are managed by the JVM (Java Virtual Machine) instead of the operating system, which minimizes the overhead associated with thread creation, scheduling, and switching. An important advantage of Virtual Threads is scalability. Since thread management overhead is significantly reduced, applications can create and manage a wide variety of Virtual Threads without performance degradation. This helps make the most of hardware resources and improves the scalability of the application.

3.2. Continuations

Continuations is a data structure that stores the state of an executing code. Continuations allow a piece of code to pause execution and then resume from where it left off. This allows Virtual Threads to pause and resume without too much overhead.

3.3. How it works to improve multithreading performance

Project Loom combines the concepts of Virtual Threads and Continuations to improve multithreading performance in Java. Instead of using traditional OS threads, Project Loom uses more lightweight Virtual Threads, which reduces costs and increases performance. Continuations help store the state of the code, allowing it to pause and resume execution without waiting for hardware resources. As a result, multi-threaded programming becomes easier, performance is improved, and application scalability is greatly increased.

4. Advantages of using Project Loom

Project Loom brings many benefits to multithreaded programming in Java, improving performance, simplifying source code, and increasing application scalability. Here are some key advantages of using Project Loom:

4.1. Higher performance

Make the most of hardware resources: Virtual Threads help applications make the most of hardware resources, such as processors and memory, providing significant performance improvements over traditional multi-threaded programming. Reduced thread management costs: Virtual Threads are managed by the JVM, which reduces costs associated with thread creation, scheduling, and switching, improving application performance.

4.2. Simplify the source code

Reduce code complexity: Project Loom simplifies multithreaded programming, reduces code complexity, and makes it easier for developers to develop and maintain applications. Easy integration with existing Java APIs: Project Loom is designed to work seamlessly with existing Java APIs, making it easy for developers to integrate and migrate to Project Loom without significant changes in Source code.

4.3. Higher scalability

Manage millions of Virtual Threads: Virtual Threads make it possible for applications to manage millions of concurrent threads without sacrificing performance, increasing the scalability of the application. Reduces synchronization problems: Project Loom helps reduce synchronization-related issues, deadlocks, and resource conflicts, making it easier for developers to manage and scale applications. Thanks to the above advantages, the application of Project Loom in Java multithreaded programming brings many significant benefits to applications and programmers.

5. How to integrate Project Loom into an existing Java project

Integrating Project Loom into an existing Java project does not require much work and significant source code changes. Here are the steps to integrate Project Loom into your Java project:

5.1. Install JDK version that supports Project Loom

To start using Project Loom in your Java project, you need to install the JDK version that supports Project Loom. Currently, Project Loom is only available in Early Access Build builds and has not been integrated into the official JDK. To install the JDK version that supports Project Loom, perform the following steps:

  1. Visit Project Loom Early Access Builds homepage at: https://jdk.java.net/loom/
  2. On the homepage, you will see JDK versions that support Project Loom for different operating systems (Windows, macOS, Linux). Choose the version that suits your operating system and download it.
  3. Unzip the downloaded file. You will get a folder containing the JDK version that supports Project Loom.
  4. To use this JDK in your project, you need to set the JAVA_HOME environment variable to point to the directory containing the extracted JDK. Follow the instructions below depending on your operating system:
    • Windows :
      1. Open Control Panel and go to System.
      2. Select “Advanced system settings”.
      3. In the “Advanced” tab, select “Environment Variables”.
      4. Create a new environment variable named JAVA_HOME and set the value to be the path to the unzipped JDK folder.
      5. Add %JAVA_HOME%bin to the Path environment variable.
    • macOS and Linux :
      1. Open Terminal.
      2. Edit the file ~/.bash_profile or ~/.bashrc (depending on the operating system and shell used) using your preferred text editor (e.g. nano , vim , emacs ).
      3. Add the following line to the newly opened file: export JAVA_HOME="/đường/dẫn/đến/thư/mục/JDK"
      4. Save the file again and close the editor.
      5. Run the following command in Terminal to update the profile: source ~/.bash_profile or source ~/.bashrc .
  5. To check the JDK installation is successful, open Terminal (on Windows, open Command Prompt) and run the command java -version . The displayed results should show that you are using a JDK version that supports Project Loom.
  6. After completing the setup of the Project Loom enabled version JDK, you need to update the configuration of your project build tool (e.g. Maven, Gradle) to use this JDK.
    • Maven : Edit the project’s pom.xml file and add or update the following:
    • Gradle : Edit the project’s build.gradle file and add or update the following:
  7. Finally, you can start using Project Loom features in your project source code, such as using virtual threads. With the above steps, you have successfully installed and set up the Project Loom-supported JDK for your Java project. Now you can continue to explore and integrate Project Loom features into your project to improve multithreading performance.

5.2. Update source code

  1. Replace traditional thread creation and management scripts with Virtual Threads. This can be achieved using Project Loom’s API such as Thread.builder().virtual().start(Runnable) or ExecutorService.newVirtualThreadExecutor() .
  2. Check and update the source code related to synchronization handling, because Project Loom helps alleviate synchronization related problems.

5.3. Test and optimize

After updating the source code, test the application again to make sure it works as expected. Perform performance analysis and optimize source code as needed, for maximum performance when using Project Loom. With the above steps, you can easily and quickly integrate Project Loom into your existing Java project, taking advantage of the advantages that Project Loom brings to multi-threaded programming.

6. Experiment and evaluate performance

6.1. Example of test application

6.1.1. Test app description

Suppose we have a simple Java application that downloads and processes data from multiple APIs. The application sends concurrent requests to the APIs and processes the results returned. We will build two versions of the application: one using traditional multithreading (using ThreadPoolExecutor ) and one using Project Loom (using ExecutorService.newVirtualThreadExecutor() ).

6.1.2. Criteria for comparison and evaluation

  • Runtime: the total running time of the application to complete all API requests.
  • Memory usage: amount of memory consumed while the application is running.
  • CPU Usage: CPU usage rate when the application is running.
  • Average latency: the average time it takes to get a result from the API.
  • Stability: how stable the application is when handling a large number of concurrent requests.

6.1.3. How to evaluate in detail

  • Use JMH (Java Microbenchmark Harness) to measure and compare the performance of two application instances on the stated criteria.
  • Generate a list of APIs and concurrent request counts for testing, e.g. 10, 50, 100, 500, 1000 concurrent requests.
  • Run the application with both approaches and execute each test at least 3 times to ensure uniformity of results.
  • Collect results from JMH and save in a data table for analysis and evaluation.

6.2. Test setup

6.2.1. Prepare application source code

We will build a simple Java application to illustrate downloading and processing data from multiple APIs. Below is the full source code for the application with two versions using ThreadPoolExecutor and Project Loom.

  1. Create an ApiRequest class to represent an API request and make the API call:
  2. Create an App class containing the main method to run the application:

6.2.2. Prepare a performance measurement tool

With the source code generated above, you can implement the application to call the APIs and process the returned results. To measure the performance of the two application instances, we will modify the App class to use JMH.

  1. Add the following to pom.xml to make sure the application uses the right Java version for Project Loom (e.g. JDK 18 or later):
  2. Create an AppBenchmark class that contains test methods for two versions of the app:
  3. Run the test methods in the AppBenchmark class and save the results in a data table. You can then analyze and evaluate the performance of the two application instances based on the results obtained. To run the tests, you can use the following command from the command line or run from your development environment (IDE)

    When you’re done, you’ll have a detailed performance result of the two versions of the app, helping to gauge the effectiveness of using Project Loom in your case.

6.2.3. Record the results

After running the test with JMH, you may get results similar to the following (results may vary depending on your hardware configuration and system resources):

In this result, Cnt is the number of test iterations, Score is the average time to complete each operation (ms/op), and Error is the standard error of the measurement result. Based on the above results, you can see that using Project Loom has resulted in significant performance improvement compared to using ThreadPoolExecutor . In this case, the application using Project Loom completed the operation about 44.5% faster than the application using ThreadPoolExecutor . Note, however, that specific performance may vary depending on your application, hardware configuration, and system resources. For a more accurate assessment, you should run tests on your development environment and analyze the results based on that.

7. The future of Project Loom and its impact on the Java developer community

Project Loom is an important project in improving the performance and reducing complexity of multithreaded applications in Java. This project is in development and will probably be integrated into JDK versions in the near future. Here are some predictions about the future of Project Loom and its impact on the Java developer community:

  • Simplify multi-threaded application development : Project Loom reduces the complexity associated with multithreading, while preserving application performance. This will make it easier for programmers to build and maintain multi-threaded applications, especially in applications that are complex or require high precision.
  • Improve Java Application Performance : With the introduction of Virtual Threads, Project Loom promises better performance for Java applications in multi-threaded scenarios. This will make Java more suitable for building applications that require high performance, such as distributed applications, web services applications or big data processing applications.
  • Backwards compatible with previous Java versions : Project Loom is designed to work with earlier versions of Java, making it easy for developers to transition to new features without worrying about changing them. change the current source code.
  • Accelerating Java Community Development : With the enhancements brought by Project Loom, the Java developer community can take advantage of new features to build better applications, as well as share knowledge and Experience in applying Project Loom to real projects.

8. Conclusion

Project Loom is an important step forward in solving the performance and complexity issues of multithreading in Java. By introducing the concept of Virtual Threads, Project Loom reduces the complexity of building multi-threaded applications, while improving application performance. In this article, we learned about the current problems of multithreading in Java, how Project Loom works, and the advantages of using Project Loom. We also ran some tests to gauge the performance of Project Loom against ThreadPoolExecutor, and took a look at the future of Project Loom and its impact on the Java developer community. If you are a Java developer, learning and applying Project Loom to your project will help you take advantage of new features, improve application performance, and reduce development complexity. . Stay tuned and join the Java community to stay up to date with the latest on Project Loom and related technologies.

9. References

  1. Goetz, B., Peierls, T., Bloch, J., Bowbeer, J., Lea, D., & Holmes, D. (2006). Java Concurrency in Practice . Addison-Wesley Professional.
  2. Loom-Proposal. (2018). Project Loom: Fibers and Continuations for the Java Virtual Machine . Retrieved from https://cr.openjdk.java.net/~rpressler/loom/Loom-Proposal.html
  3. Sandoz, P. (2020). State of Loom . Oracle Code One. Retrieved from https://www.youtube.com/watch?v=lI0ke7QGclc
  4. Baeldung. (2022). OpenJDK Project Loom . Baeldung. Retrieved from https://www.baeldung.com/openjdk-project-loom
  5. Lea, D. (2004). A Java Fork/Join Framework . Proceedings of the ACM 2000 Conference on Java Grande. Retrieved from http://gee.cs.oswego.edu/dl/papers/fj.pdf
  6. OpenJDK. (2021). The Java Tutorials: Concurrency . Oracle. Retrieved from https://docs.oracle.com/javase/tutorial/essential/concurrency/
  7. OpenJDK. (2021). Project Loom Early-Access Builds . Oracle. Retrieved from https://jdk.java.net/loom/
  8. Evans, B. (2021). Going inside Java’s Project Loom and virtual threads. Java Magazine. Retrieved from https://blogs.oracle.com/javamagazine/post/going-inside-javas-project-loom-and-virtual-threads
  9. Pressler, R., & Humble, C. (2021). Java’s Project Loom, Virtual Threads and Structured Concurrency with Ron Pressler. InfoQ. Retrieved from https://www.infoq.com/podcasts/java-project-loom/
Share the news now

Source : Viblo