# Refactoring for Java-Structured Concurrency
## 7 Evaluation
### Research Questions
#### 7.3.4 Results of RQ4  
To answer RQ4, we selected _Light-4j, ModernJava_, and _Codelam_ for performance testing. We recorded the execution times of these methods before and after refactoring and tested their performances for various task quantities.  
For the project _Light-4j_, we selected _Http2 ClientPoolTest_, _Http2 ClientTest_, and _Http2 ClientPoolIT_ for testing. Figure 7a illustrates the execution times of these methods. After refactoring, the execution times of these methods in _Http2 ClientPoolTest_ reduced by 9.9%. The execution times of these methods in _Http2 ClientPoolIT_ showed a reduction of 5.8%, while the execution times of these methods in _Http2 ClientTest_ showed a decrease of 6.3% after refactoring. For the _ModernJava_ project, we selected _TestMovieDb_, _LinkScraper_, and _ThreadPrimeNumberFinder_ for testing, with the results shown in Figure 7b. After refactoring, these methods in _TestMovieDb_ showed a 16.6% reduction in execution time, while these methods in _LinkScraper_ showed a more significant reduction of 5.3%. Finally, the execution times of these methods in _ThreadPrimeNumberFinder_ reduced by 7.3%. As is evident therefrom, with regard to diverse projects, refactoring is capable of leading to enhancements in execution efficiency.  
We also evaluated the changes in the throughput before and after refactoring for _HttpClientTest_ in _Light-4j_ and _SenateExucuationMT_ in _Codelam_, with varying task counts ranging from 20 to 400, as shown in Figure 8. For _HttpClientTest_, the throughput before refactoring showed significant variability with different task quantities, as shown in Figure 8a. As the number of tasks increased from 20 to 400, the rate of the decrease in the performance  
\begin{table}
\begin{tabular}{c c c c c} \hline \hline
**Project** & **SLOC1** & **SLOC2** & **Changed** & **Time (s)** \\ \hline SystemML & 412,560 & 412,661 & 101 & 63.8 \\ BigStitcher & 15,584 & 15,612 & 28 & 14.5 \\ Light-4j & 74,371 & 74,406 & 35 & 31.5 \\ MetaOmGraph & 80,177 & 80,198 & 21 & 33.3 \\ ModernJava & 23,045 & 23,063 & 18 & 17.8 \\ TrackMate & 58,873 & 58,898 & 25 & 24.8 \\ CodeJam & 11,106 & 11,130 & 24 & 12.3 \\ \hline SUM/AVG & 675,716 & 675,968 & 252 & 191/27.3 \\ \hline \hline \end{tabular}
\end{table}
Table 3: Refactoring results of ReStruct (2).  
continued to increase. During this period, the overall throughput dropped by 55.4%. When the number of tasks increased beyond 400, even memory overflow errors occurred. In contrast, the refactored code exhibited minimal fluctuations in the throughput with varying task numbers, showing only an 11.4% reduction in throughput when the number of tasks increased. For _SenateEvacuationMT_, the throughput variations before and after refactoring are generally consistent with different task quantities, as shown in Figure 7(b). When the number of tasks increased from 20 to 400, the throughput for both the refactored and non-refactored code decreased by approximately 94%. The reason is that the underlying structure of the structured concurrency is based on virtual threads, which are lightweight threads attached to platform threads and significantly outnumber them. When handling I/O-bound tasks, the CPU often remains idle for extended periods, and the key factors limiting the program's execution efficiency are the switching between threads and limitations on the number of threads. Because virtual threads are more lightweight than platform threads, they incur less switching overhead and can be provided in a much larger quantity. However, for CPU-bound tasks, the primary factor affecting the execution efficiency shifts to the CPU's processing capability. Therefore, there are not many differences in performance before and after refactoring. However, in a multithreaded program, it can still reduce the overhead of the thread switching.