# Automatically Injecting Robustness Statements into Distributed Applications
## 5 Results  
To evaluate the gains of our proposed code transformations, we performed experiments on a sample distributed application designed to extract data from the Amazon BooksReviews dataset [40], enabling the inference of characteristics related to books, authors, and reviews. The dataset consists of around 3 million book reviews authored by a large user base, and covers a diverse corpus of 212,404 distinct books. To ensure a manageable execution time during testing for transformation correctness and performance evaluation, a subset of around 200,000 reviews were selected. The application's source code is publicly accessible via a dedicated repository [41]. Figures 2 and 3 show the UML class diagrams outlining the application's components. The DataService remote interface defines five methods: getAuthors(), getMostReviewedBook(), getLeastReviewedBook(), getAverageReviewedBook(), and getAverageReviewedBook(). The Server class creates and configures an instance of Service, which implements the DataService interface and uses the methods of the ExtractDataset class to retrieve information from the book dataset. On the client side, the ServiceProxy class implements DataService and manages network communication, performing RMIs on the methods exposed by Service. The Client  
Figure 3: The UML class diagram of the client-side architecture. Figure 2: The UML class diagram of the server-side architecture. class creates a ServiceProxy object to connect to the service and receive the results of remote method executions. An analysis of the Client class identified four methods suitable for transformation, each involving two distinct RMI calls to extract some data from the dataset. As seen previously, Listing 1 shows a method of the origin Client class that was automatically converted into the robust and parallel version shown in Listing 2. To evaluate the performance of the refactored version, we used the Java Microbenchmark Harness (JMH), a standardized tool for conducting rigorous performance tests. Our setup included warming up the execution environment to ensure reliable performance metrics: each benchmark consisted of five warm-up iterations followed by ten normal iterations. JMH tests are particularly suited for assessing performance improvements as they isolate the evaluated subject from external influences. We performed four benchmarks for each refactored method. Each benchmark table shown below follows a consistent structure: the \"ith-run\" column indicates the iteration number; \"sequential time (ms)\", and \"parallel time (ms)\" display the execution time in milliseconds per iteration for the two versions; and \"speed-up\" denotes the performance gain achieved by the parallel version (computed as \(((runtime_{old}-runtime_{new})/runtime_{old})\times 100\)). This allows for a detailed comparison of performance improvements achieved in the refactored version, validating its effectiveness in enhancing application robustness and efficiency under controlled testing conditions. Tables 1, 2, 3 and 4 show, respectively, the resulting benchmarks for the following methods: extractAverageReviewedAuthor(), extractLeastReviewedAuthor(), extractMostReviewedAuthor(), and getUserForAuthor(). An additional benchmark was executed to assess the resilience of the distributed system both before and after our transformation. Table 5 presents the benchmark results for the getUserForAuthor() method, which was executed while simulating communication failures during the RMI calls. The \"ith run\" column indicates the iteration number, while the \"delay (ms)\" column displays the network delay in milliseconds occurring during the RMI call. The columns labeled \"mini-time (ms)\" and \"mod-time (ms)\" represent the execution times for the original RMI version and the modified RMI version proposed by our approach, respectively.