# An Automatic Transformer from Sequential to Parallel Java Code
## 6 Experiments and Results
### Code Analysis and Transformation  
Among the 44 methods in the six classes of the application under analysis, our tool automatically identified five methods that were refactored to a parallel version accordingly. Listing 7 shows one of such methods, getUserForAuthor(HashMap<String, Book> books, List<Review> reviews), which has been automatically analyzed as follows.  
Method call getAuthors() at line 2 (Listing 7) was selected; firstly, the context was such that further assessment was undertaken, as the context of the method call was one of the feasible cases detailed in Section 4.1; the data dependence analysis identified the instruction at line 4 as data-dependent, because the authors list was filled by the method call at line 2 and then was used at line 4. Then, the CFG was built (composed of statements in the called methods) and conditional branches and loops were analyzed to possibly perform some adjustments (see Section 5.2); the code was free from any if/else statement; hence, the CFG had no alternative paths. Moreover, the CFG had no loops. Then, possible parallel paths were found. Finally, the path comprising line 2 (including the CFG of the called method), and the path comprising line 3 (including the CFG of the called method) were automatically assessed to count the number of instructions constituting them, and then determine if their parallel execution would provide performance gains.  
```
publicstaticHashMap<String,Author>getUserForAuthor(HashMap<String,Book>books,List<Review>review>){
1 ExtractDataextractor=newExtractData(books,reviews);
2 HashMap<String,Author>authors=extractor.getAuthors();
3 HashMap<String,User>users=extractor.getUserForAuthor();
4 authors.values().forEach(author>{
5 List<String>userId=author.getNodes().stream().
6 flatMap(b->b.getReviews().stream().map(r->r.getUserID())).
7 collect(Collectors.toList());
8 usersId.forEach(u->author.addUser(users.get(u)));
9});
10 returnauthors; } //parallelversionofsomeinstructionsabove
2 CompletableFuture<HashMap<String,Author>f=CompletableFuture.supplyAsync(()->extractor.getAuthors());
3 HashMap<String,User>users=extractor.getUserForAuthor();
4 HashMap<String,Author>authors=f.get();
```  
**Listing 7**. Extracting the authors from the books and the users from the reviews; then assigning to each author all the users that provided at least one review for the author's books.  
Figure 3 shows a portion of the CFG for the code in Listing 7, from line 1 to line 5. The paths that should be executed in parallel are (i) the instruction at line 2; (ii) the instruction at line 3. Line 4 presents a statement that depends on the output of line 2. The first path has nine instructions, eight are the instructions contained in the CFG\({}_{2}\), of which, six are inside a loop. The second path has 10 instructions, 11 are the instructions contained in the CFG\({}_{3}\), of which, 5 are inside a loop. The method is suitable for parallel refactoring because the instruction numbers are sufficiently large and both CFGs found contain a loop.  
Therefore, a new version of the method has been generated that contains the constructs for parallel execution. Such a version can be seen in the bottom part of Listing 7; the method call was given as a lambda expression in the CompletableFuture call supplyAsync(); just after line 3, the get() call was introduced to synchronize the execution and create the authors HashMap.  
Figure 3: CFG extracted from method getUserForAuthor() shown in Listing 7.