Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams

183 views

Published on

Streaming APIs are becoming more pervasive in mainstream Object-Oriented programming languages. For example, the Stream API introduced in Java 8 allows for functional-like, MapReduce-style operations in processing both finite and infinite data structures. However, using this API efficiently involves subtle considerations like determining when it is best for stream operations to run in parallel, when running operations in parallel can be less efficient, and when it is safe to run in parallel due to possible lambda expression side-effects. In this paper, we present an automated refactoring approach that assists developers in writing efficient stream code in a semantics-preserving fashion. The approach, based on a novel data ordering and typestate analysis, consists of preconditions for automatically determining when it is safe and possibly advantageous to convert sequential streams to parallel and unorder or de-parallelize already parallel streams. The approach was implemented as a plug-in to the Eclipse IDE, uses the WALA and SAFE analysis frameworks, and was evaluated on 11 Java projects consisting of $\sim$642 thousand lines of code. We found that 36.31% of candidate streams were refactorable, and an average speedup of 3.49 on performance tests was observed. The results indicate that the approach is useful in optimizing stream code to their full potential.

Published in: Technology
  • DOWNLOAD FULL BOOKS, INTO AVAILABLE FORMAT ......................................................................................................................... ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. PDF EBOOK here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. EPUB Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... 1.DOWNLOAD FULL. doc Ebook here { https://tinyurl.com/y3nhqquc } ......................................................................................................................... ......................................................................................................................... ......................................................................................................................... .............. Browse by Genre Available eBooks ......................................................................................................................... Art, Biography, Business, Chick Lit, Children's, Christian, Classics, Comics, Contemporary, Cookbooks, Crime, Ebooks, Fantasy, Fiction, Graphic Novels, Historical Fiction, History, Horror, Humor And Comedy, Manga, Memoir, Music, Mystery, Non Fiction, Paranormal, Philosophy, Poetry, Psychology, Religion, Romance, Science, Science Fiction, Self Help, Suspense, Spirituality, Sports, Thriller, Travel, Young Adult,
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams

  1. 1. Safe Automated Refactoring for Intelligent Parallelization of Java 8 Streams Raffi Khatchadourian1,2 Yiming Tang2 Mehdi Bagherzadeh3 Syed Ahmed3 International Conference on Software Engineering May 31, 2019, Montr´eal, Canada 1 Computer Science, City University of New York (CUNY) Hunter College, USA 2 Computer Science, City University of New York (CUNY) Graduate Center, USA 3 Computing Science & Engineering, Oakland University, USA
  2. 2. Introduction
  3. 3. Streaming APIs • Streaming APIs are widely-available in today’s mainstream, Object-Oriented programming languages [Biboudis et al., 2015]. 1
  4. 4. Streaming APIs • Streaming APIs are widely-available in today’s mainstream, Object-Oriented programming languages [Biboudis et al., 2015]. • Incorporate MapReduce-like operations on native data structures like collections. 1
  5. 5. Streaming APIs • Streaming APIs are widely-available in today’s mainstream, Object-Oriented programming languages [Biboudis et al., 2015]. • Incorporate MapReduce-like operations on native data structures like collections. • Can make writing parallel code easier, less error-prone (avoid data races, thread contention). 1
  6. 6. Motivation
  7. 7. Problem • MapReduce traditionally runs in highly-distributed environments with no shared memory. 2
  8. 8. Problem • MapReduce traditionally runs in highly-distributed environments with no shared memory. • Streaming APIs typically execute on a single node under multiple threads or cores in a shared memory space. 2
  9. 9. Problem • MapReduce traditionally runs in highly-distributed environments with no shared memory. • Streaming APIs typically execute on a single node under multiple threads or cores in a shared memory space. • Collections reside in local memory. 2
  10. 10. Problem • MapReduce traditionally runs in highly-distributed environments with no shared memory. • Streaming APIs typically execute on a single node under multiple threads or cores in a shared memory space. • Collections reside in local memory. • Issues may arise from close ties between shared memory and the operations. 2
  11. 11. Problem • MapReduce traditionally runs in highly-distributed environments with no shared memory. • Streaming APIs typically execute on a single node under multiple threads or cores in a shared memory space. • Collections reside in local memory. • Issues may arise from close ties between shared memory and the operations. • Developers must manually determine whether running stream code in parallel is efficient yet interference-free. 2
  12. 12. Problem • MapReduce traditionally runs in highly-distributed environments with no shared memory. • Streaming APIs typically execute on a single node under multiple threads or cores in a shared memory space. • Collections reside in local memory. • Issues may arise from close ties between shared memory and the operations. • Developers must manually determine whether running stream code in parallel is efficient yet interference-free. • Requires thorough understanding of the API. 2
  13. 13. Problem • MapReduce traditionally runs in highly-distributed environments with no shared memory. • Streaming APIs typically execute on a single node under multiple threads or cores in a shared memory space. • Collections reside in local memory. • Issues may arise from close ties between shared memory and the operations. • Developers must manually determine whether running stream code in parallel is efficient yet interference-free. • Requires thorough understanding of the API. • Error-prone, possibly requiring complex analysis. 2
  14. 14. Problem • MapReduce traditionally runs in highly-distributed environments with no shared memory. • Streaming APIs typically execute on a single node under multiple threads or cores in a shared memory space. • Collections reside in local memory. • Issues may arise from close ties between shared memory and the operations. • Developers must manually determine whether running stream code in parallel is efficient yet interference-free. • Requires thorough understanding of the API. • Error-prone, possibly requiring complex analysis. • Omission-prone, optimization opportunities may be missed. 2
  15. 15. Motivating Example 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream()parallelStream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); 3
  16. 16. Motivating Example 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream()parallelStream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); • We can perform the transformation at line 3 because the operations do not access shared memory, i.e., no side-effects. 3
  17. 17. Motivating Example 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream()parallelStream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); • We can perform the transformation at line 3 because the operations do not access shared memory, i.e., no side-effects. • Had the stream been ordered, however, running in parallel may result in worse performance due to sorted() requiring multiple passes and data buffering. 3
  18. 18. Motivating Example 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream()parallelStream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); • We can perform the transformation at line 3 because the operations do not access shared memory, i.e., no side-effects. • Had the stream been ordered, however, running in parallel may result in worse performance due to sorted() requiring multiple passes and data buffering. • Such operations are called stateful intermediate operations (SIOs). 3
  19. 19. Motivating Example 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); 1 List<Widget> sortedWidgets 2 = unorderedWidgets 3 .stream()parallelStream() 4 .sorted(Comparator 5 .comparing( 6 Widget::getWeight)) 7 .collect( 8 Collectors.toList()); • We can perform the transformation at line 3 because the operations do not access shared memory, i.e., no side-effects. • Had the stream been ordered, however, running in parallel may result in worse performance due to sorted() requiring multiple passes and data buffering. • Such operations are called stateful intermediate operations (SIOs). • Maintaining data ordering is detrimental to parallel performance. 3
  20. 20. Motivating Example 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); 4
  21. 21. Motivating Example 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); • Computation is already in parallel (line 7). 4
  22. 22. Motivating Example 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); • Computation is already in parallel (line 7). • distinct() is an SIO and the stream is ordered. 4
  23. 23. Motivating Example 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); • Computation is already in parallel (line 7). • distinct() is an SIO and the stream is ordered. • Can we keep it in parallel? No, because TreeSets are ordered. 4
  24. 24. Motivating Example 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); 1 // collect distinct widget 2 // weights into a TreeSet. 3 Set<Double> 4 distinctWeightSet = 5 orderedWidgets 6 .stream() 7 .parallel() 8 .map(Widget::getWeight) 9 .distinct() 10 .collect(Collectors 11 .toCollection( 12 TreeSet::new)); • Computation is already in parallel (line 7). • distinct() is an SIO and the stream is ordered. • Can we keep it in parallel? No, because TreeSets are ordered. • De-parallelize on line 7. 4
  25. 25. Approach
  26. 26. Solution • Devised a fully-automated, semantics-preserving refactoring approach. 5
  27. 27. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. 5
  28. 28. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. • Transforms Java 8 stream code for improved performance. 5
  29. 29. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. • Transforms Java 8 stream code for improved performance. • Based on: 5
  30. 30. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. • Transforms Java 8 stream code for improved performance. • Based on: • Novel ordering analysis. 5
  31. 31. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. • Transforms Java 8 stream code for improved performance. • Based on: • Novel ordering analysis. • Infers when maintaining ordering is necessary for semantics preservation. 5
  32. 32. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. • Transforms Java 8 stream code for improved performance. • Based on: • Novel ordering analysis. • Infers when maintaining ordering is necessary for semantics preservation. • Typestate analysis [Fink et al., 2008; Strom and Yemini, 1986]. 5
  33. 33. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. • Transforms Java 8 stream code for improved performance. • Based on: • Novel ordering analysis. • Infers when maintaining ordering is necessary for semantics preservation. • Typestate analysis [Fink et al., 2008; Strom and Yemini, 1986]. • Augments the type system with “state.” 5
  34. 34. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. • Transforms Java 8 stream code for improved performance. • Based on: • Novel ordering analysis. • Infers when maintaining ordering is necessary for semantics preservation. • Typestate analysis [Fink et al., 2008; Strom and Yemini, 1986]. • Augments the type system with “state.” • Traditionally used for preventing resource usage errors. 5
  35. 35. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. • Transforms Java 8 stream code for improved performance. • Based on: • Novel ordering analysis. • Infers when maintaining ordering is necessary for semantics preservation. • Typestate analysis [Fink et al., 2008; Strom and Yemini, 1986]. • Augments the type system with “state.” • Traditionally used for preventing resource usage errors. • Requires interprocedural and alias analyses. 5
  36. 36. Solution • Devised a fully-automated, semantics-preserving refactoring approach. • Embodied by an open source refactoring tool named Optimize Streams. • Transforms Java 8 stream code for improved performance. • Based on: • Novel ordering analysis. • Infers when maintaining ordering is necessary for semantics preservation. • Typestate analysis [Fink et al., 2008; Strom and Yemini, 1986]. • Augments the type system with “state.” • Traditionally used for preventing resource usage errors. • Requires interprocedural and alias analyses. • Novel adaptation for possibly immutable objects (streams). 5
  37. 37. Solution Highlights • First to integrate automated refactoring with typestate analysis.1 1To the best of our knowledge. 2http://wala.sf.net 3http://git.io/vxwBs 6
  38. 38. Solution Highlights • First to integrate automated refactoring with typestate analysis.1 • Uses WALA static analysis framework2 and the SAFE typestate analysis engine.3 1To the best of our knowledge. 2http://wala.sf.net 3http://git.io/vxwBs 6
  39. 39. Solution Highlights • First to integrate automated refactoring with typestate analysis.1 • Uses WALA static analysis framework2 and the SAFE typestate analysis engine.3 • Combines analysis results from varying IR representations (SSA, AST). 1To the best of our knowledge. 2http://wala.sf.net 3http://git.io/vxwBs 6
  40. 40. Identifying Refactoring Preconditions • Refactoring preconditions are conditions that must hold to guarantee that the transformation is type-correct and semantics-preserving. 7
  41. 41. Identifying Refactoring Preconditions • Refactoring preconditions are conditions that must hold to guarantee that the transformation is type-correct and semantics-preserving. • Our refactoring is (conceptually) split into two: 7
  42. 42. Identifying Refactoring Preconditions • Refactoring preconditions are conditions that must hold to guarantee that the transformation is type-correct and semantics-preserving. • Our refactoring is (conceptually) split into two: • Convert Sequential Stream to Parallel. 7
  43. 43. Identifying Refactoring Preconditions • Refactoring preconditions are conditions that must hold to guarantee that the transformation is type-correct and semantics-preserving. • Our refactoring is (conceptually) split into two: • Convert Sequential Stream to Parallel. • Optimize Parallel Stream. 7
  44. 44. Identifying Refactoring Preconditions Table 1: Convert Sequential Stream to Parallel preconditions. exe ord se SIO ROM transformation P1 seq unord F N/A N/A Convert to para. P2 seq ord F F N/A Convert to para. P3 seq ord F T F Unorder and convert to para. 8
  45. 45. Identifying Refactoring Preconditions Table 2: Optimize Parallel Stream preconditions. exe ord SIO ROM transformation P4 para ord T F Unorder. P5 para ord T T Convert to seq. 9
  46. 46. DFA for Determining Stream Execution Mode ⊥ start seq para Col.stream(), BufferedReader.lines(), Files.lines(Path), JarFile.stream(), Pattern.splitAsStream(), Random.ints() Col.parallelStream() BaseStream.sequential() BaseStream.parallel() BaseStream.sequential() BaseStream.parallel() Figure 1: A subset of the relation E→ in E = (ES , EΛ, E→). 10
  47. 47. DFA for Determining Stream Ordering ⊥ start ord unord Arrays.stream(T[]), Stream.of(T...), IntStream.range(), Stream.iterate(), BitSet.stream(), Col.parallelStream() Stream.generate(), HashSet.stream(), PriorityQueue.stream(), CopyOnWrite.parallelStream(), BeanContextSupport.stream(), Random.ints() Stream.sorted() BaseStream.unordered(), Stream.concat(unordered), Stream.concat(ordered) Stream.sorted(), Stream.concat(ordered) BaseStream.unordered(), Stream.concat(unordered) Figure 2: A subset of the relation O→ in O = (OS , OΛ, O→). 11
  48. 48. Evaluation
  49. 49. Optimize Streams Eclipse Refactoring Plug-in • Implemented an open source refactoring tool named Optimize Streams. 4http://eclipse.org. 5Available at http://git.io/vpTLk. 12
  50. 50. Optimize Streams Eclipse Refactoring Plug-in • Implemented an open source refactoring tool named Optimize Streams. • Publicly available as an open source Eclipse IDE4 plug-in.5 4http://eclipse.org. 5Available at http://git.io/vpTLk. 12
  51. 51. Optimize Streams Eclipse Refactoring Plug-in • Implemented an open source refactoring tool named Optimize Streams. • Publicly available as an open source Eclipse IDE4 plug-in.5 • Can we be used by projects not using Eclipse. 4http://eclipse.org. 5Available at http://git.io/vpTLk. 12
  52. 52. Optimize Streams Eclipse Refactoring Plug-in • Implemented an open source refactoring tool named Optimize Streams. • Publicly available as an open source Eclipse IDE4 plug-in.5 • Can we be used by projects not using Eclipse. • Includes fully-functional UI, preview pane, and refactoring unit tests. 4http://eclipse.org. 5Available at http://git.io/vpTLk. 12
  53. 53. Results • Applied to 11 Java projects of varying size and domain with a total of ∼642 KSLOC. 13
  54. 54. Results • Applied to 11 Java projects of varying size and domain with a total of ∼642 KSLOC. • 36.31% candidate streams were refactorable. 13
  55. 55. Results • Applied to 11 Java projects of varying size and domain with a total of ∼642 KSLOC. • 36.31% candidate streams were refactorable. • Observed an average speedup of 3.49 during performance testing. 13
  56. 56. Results • Applied to 11 Java projects of varying size and domain with a total of ∼642 KSLOC. • 36.31% candidate streams were refactorable. • Observed an average speedup of 3.49 during performance testing. • See paper and [Khatchadourian et al., 2018] for more details, including user feedback, as well as tool and data set engineering challenges. 13
  57. 57. Results Table 3: Experimental results. subject KLOC eps k str rft P1 P2 P3 t (m) htm.java 41.14 21 4 34 10 0 10 0 1.85 JacpFX 23.79 195 4 4 3 3 0 0 2.31 jdp* 19.96 25 4 28 15 1 13 1 31.88 jdk8-exp* 3.43 134 4 26 4 0 4 0 0.78 jetty 354.48 106 4 21 7 3 4 0 17.85 jOOQ 154.01 43 4 5 1 0 1 0 12.94 koral 7.13 51 3 6 6 0 6 0 1.06 monads 1.01 47 2 1 1 0 1 0 0.05 retroλ 5.14 1 4 8 6 3 3 0 0.66 streamql 4.01 92 2 22 2 0 2 0 0.72 threeten 27.53 36 2 2 2 0 2 0 0.51 Total 641.65 751 4 157 57 10 46 1 70.60 * jdp is java-design-patterns and jdk8-exp is jdk8-experiments. 14
  58. 58. Performance Evaluation Table 4: Average run times of JMH benchmarks. # benchmark orig (s/op) refact (s/op) su 1 shouldRetrieveChildren 0.011 (0.001) 0.002 (0.000) 6.57 2 shouldConstructCar 0.011 (0.001) 0.001 (0.000) 8.22 3 addingShouldResultInFailure 0.014 (0.000) 0.004 (0.000) 3.78 4 deletionShouldBeSuccess 0.013 (0.000) 0.003 (0.000) 3.82 5 addingShouldResultInSuccess 0.027 (0.000) 0.005 (0.000) 5.08 6 deletionShouldBeFailure 0.014 (0.000) 0.004 (0.000) 3.90 7 specification.AppTest.test 12.666 (5.961) 12.258 (1.880) 1.03 8 CoffeeMakingTaskTest.testId 0.681 (0.065) 0.469 (0.009) 1.45 9 PotatoPeelingTaskTest.testId 0.676 (0.062) 0.465 (0.008) 1.45 10 SpatialPoolerLocalInhibition 1.580 (0.168) 1.396 (0.029) 1.13 11 TemporalMemory 0.013 (0.001) 0.006 (0.000) 1.97 15
  59. 59. Conclusion
  60. 60. Conclusion • Optimize Streams is an open source, automated refactoring tool that assists developers with writing optimal Java 8 Stream code. 16
  61. 61. Conclusion • Optimize Streams is an open source, automated refactoring tool that assists developers with writing optimal Java 8 Stream code. • Integrates an Eclipse refactoring with the advanced static analyses offered by WALA and SAFE. 16
  62. 62. Conclusion • Optimize Streams is an open source, automated refactoring tool that assists developers with writing optimal Java 8 Stream code. • Integrates an Eclipse refactoring with the advanced static analyses offered by WALA and SAFE. • 11 Java projects totaling ∼642 thousands of lines of code were used in the tool’s assessment. 16
  63. 63. Conclusion • Optimize Streams is an open source, automated refactoring tool that assists developers with writing optimal Java 8 Stream code. • Integrates an Eclipse refactoring with the advanced static analyses offered by WALA and SAFE. • 11 Java projects totaling ∼642 thousands of lines of code were used in the tool’s assessment. • An average speedup of 3.49 on the refactored code was observed as part of a experimental study. 16
  64. 64. For Further Reading Biboudis, Aggelos, Nick Palladinos, George Fourtounis, and Yannis Smaragdakis (2015). “Streams `a la carte: Extensible Pipelines with Object Algebras”. In: ECOOP, pp. 591–613. doi: 10.4230/LIPIcs.ECOOP.2015.591. Fink, Stephen J., Eran Yahav, Nurit Dor, G. Ramalingam, and Emmanuel Geay (May 2008). “Effective Typestate Verification in the Presence of Aliasing”. In: ACM TOSEM 17.2, pp. 91–934. doi: 10.1145/1348250.1348255. Khatchadourian, Raffi, Yiming Tang, Mehdi Bagherzadeh, and Syed Ahmed (Sept. 2018). “A Tool for Optimizing Java 8 Stream Software via Automated Refactoring”. In: International Working Conference on Source Code Analysis and Manipulation. SCAM ’18. Engineering Track. Distinguished Paper Award. IEEE. IEEE Press, pp. 34–39. doi: 10.1109/SCAM.2018.00011. Strom, Robert E and Shaula Yemini (Jan. 1986). “Typestate: A programming language concept for enhancing software reliability”. In: IEEE TSE SE-12.1, pp. 157–171. doi: 10.1109/tse.1986.6312929. 17

×