1 of 49

LeakPair: Proactive Repairing of

Leaks in Single Page Web Applications

Arooba Shahoor�Department of Computer Science and Engineering

Kyungpook National University, Korea�June 5, 2024

2 of 49

2

3 of 49

MOTIVATION

3

4 of 49

4

What is a memory leak?

Continuous allocation of memory without releasing it when no longer used.

Continuous reduction in available memory.

5 of 49

The Rise of Single Page Apps (SPAs)

5

  • Up until early 2000’s, Multi Page Application (MPA) was the only website architecture.

  • Shift to SPA increasing rapidly.

6 of 49

Why Are Memory Leaks Critical in the SPA Architecture?

6

7 of 49

Multi Page Application Architecture

7

Client

Page switching with reload

User Interface

Page 1

Page 2

Page 3

HTTP Request for initial page load

HTTP Request for page transition

Server

<template>

Presentation Layer

Database & Business Logic

New page for each request

Inside the Heap

Object 3

Object 2

Object 4

Object 1

Allocated objects from previous page all wiped off

On user interactions

8 of 49

Single Page Application Architecture

8

Client

No reload required

SPA Framework (Angular/React/Vue..)

Single .html file

<template 1>

<template 2>

<template 3>

View switching without reload

User Interface

View 1

View 2

View 3

HTTP Request for initial page load

AJAX Request for page transition

Server

Database & Business Logic

Object 3

Object 4

Object 2

Object 1

Object 6

Object 5

This page is never refreshed…

On user interactions

Inside the Heap

Unintentional references will keep piling up!

Object 7

Object 8

Object 9

9 of 49

JavaScript Devs Can’t Rely on Garbage Collectors

9

10 of 49

Garbage Collection in JS (Mark and Sweep)

Reachability from Root

10

Object 4

Object 5

Object 2

Object 8

Object 6

Object 7

Object 3

Object 1

View 1 (Inside Heap)

window

(GC ROOT 1)

String

(GC ROOT 2)

11 of 49

Garbage Collection in JS (Mark and Sweep)

Reachability from Root

11

Object 4

Object 5

Object 2

Object 8

UNUSED

Object 7

UNUSED

Object 1

View 2 (Inside Heap)

UNUSED

UNUSED

window

(GC ROOT 1)

String

(GC ROOT 2)

12 of 49

Garbage Collection in JS (Mark and Sweep)

Reachability from Root

12

UNUSED

MARK

Object 5

MARK

Object 2

MARK

UNUSED

MARK

UNUSED

MARK

Object 7

SWEEP

UNUSED

MARK

Object 1

MARK

View 2 (Inside Heap)

Unused objects marked as alive and will not be GC’ed, due to reachability from GC root

window

(GC ROOT 1)

String

(GC ROOT 2)

13 of 49

Garbage Collection in JS (Mark and Sweep)

Reachability from Root

13

UNUSED

MARK

Object 5

MARK

Object 2

MARK

UNUSED

MARK

UNUSED

MARK

UNUSED

MARK

Object 1

MARK

View 2 (Inside Heap)

window

(GC ROOT 1)

String

(GC ROOT 2)

14 of 49

Garbage Collection in JS (Mark and Sweep)

Reachability from Root

14

UNUSED

Object 5

Object 2

UNUSED

UNUSED

UNUSED

Object 1

View 3 (Inside Heap)

window

(GC ROOT 1)

String

(GC ROOT 2)

New object 1

New object 2

Lingering unwanted objects will keep gobbling up available space for newer objects

New object 3

15 of 49

Case in Point

15

Memory Leak in MS Rooster [2]

Reachable from root

The fix

16 of 49

16

Impact of Memory Leaks(Why Not to Ignore)

  • Slower Performance.
  • Freezing/Not Responding.
  • Crashing.

17 of 49

17

How often?

  • Not a once in a while issue.

  • More than 99% of Google Chrome crashes on low-end Android phones.

  • 50 memory leaks across JavaScript frameworks, Google apps.

S. H. Jensen, M. Sridharan, K. Sen, and S. Chandra, ‘MemInsight: platform-independent memory debugging for JavaScript’, in Proceedings of the 2015 10th Joint Meeting on Foundations of Software Engineering, New York, NY, USA, Aug. 2015, pp. 345–356. doi: 10.1145/2786805.2786860

18 of 49

18

So why no one is talking about it?

19 of 49

19

20 of 49

Leak Detection in JS

Automation Efforts (2015-2022)

2015. MemInsight

2016. LeakSpot

2018. BLeak

2022. Memlab

20

S. H. Jensen, M. Sridharan, K. Sen, and S. Chandra, ‘MemInsight: platform-independent memory debugging for JavaScript’, in Proceedings of the 2015 10th Joint Meeting on Foundations of Software Engineering, New York, NY, USA, Aug. 2015, pp. 345–356. doi: 10.1145/2786805.2786860

M. Rudafshani and P. A. Ward, “LeakSpot: Detection and diagnosis of memory leaks in JavaScript Applications,” Software: Practice and Experience, vol. 47, no. 1, pp. 97–123, 2016.

J.Vilk and E. D. Berger, “BLeak: automatically debugging memory leaks in web applications,” in Proceedings of the 39th ACM SIGPLAN Conference on Programming Language Design and Implementation, New York, NY, USA, Jun. 2018, pp. 15–29. doi: 10.1145/3192366.3192376.

https://facebook.github.io/memlab/

21 of 49

The Problem With Automated Detection Tools

MemInsight

LeakSpot

21

BLeak

Memlab

Based on staleness criteria + report leak-related data rather than actual leak locations

Takes at least 10 mins to execute

Reported retainer traces contain metadata and internal objects, making root cause detection arduous

Require manually-written scenario file

22 of 49

State of the Art

  • Manual diagnosis via heap snapshots.
  • Three snapshot technique.
  • First introduced by Gmail team in 2012.
  • Detecting root cause can be laborious and inaccurate.

22

23 of 49

A change of perspective

23

What we need is…

24 of 49

Proactive Approach

Based on fix patterns.

  • Fix first without detection.
  • Patches that are simple, non-intrusive and recurring.
  • Enable repairs before fault localization.
  • Avoiding detection step is a huge advantage.

24

D. Kim, J. Nam, J. Song, and S. Kim, “Automatic patch generation learned from human-written patches,” in 2013 35th International Conference on Software Engineering (ICSE). San Francisco, CA, USA: IEEE, 2013, pp. 802–811

25 of 49

LeakPair

25

26 of 49

Leak Pattern Mining

  • Search targets: GitHub and Stack Overflow.
  • Reported at least 5 times.
  • Acknowledged by at least 2 developers.
  • Replicable and testable.

26

27 of 49

Fix Pattern Mining

  • Stack Overflow answers accepted at least in 2 posts.
  • GitHub commits merged in at least 2 different projects.
  • Verified by comparing memory footprints before and after.

27

28 of 49

5 Leaks and (Corresponding) Fix Patterns

28

29 of 49

1. Uncleared Timing Events (setTimeout and setInterval)

29

{

setTimeOut(() => {...})

}

{

- setTimeOut(() => {...})

+ timeOutID = setTimeOut(() => {...})

...

+ destructorMethodDeclaration() {

...

+ clearTimeOut(timeOutID)

+ }

}

If component unmounts before time, these events will still execute, retaining references of all enclosing objects.

Fix Pattern

Leak Pattern

30 of 49

2. Unremoved Event Listener

30

function listenerHandler() {

...

}

...

eventTarget

.addEventListener(eventType, listenerHandler)

{

function listenerHandler() {

...

}

...

eventTarget

.addEventListener(eventType, listenerHandler, options)

...

+ destructorMethodDeclaration() {

...

+ eventTarget.removeEventListener(eventType, listenerHandler)

+ }

}

Event listeners retain references of all enclosing variables.

Fix Pattern

Leak Pattern

31 of 49

3. Uncancelled Animation Frame Requests

31

{

requestAnimationFrame(() => {...})

}

�+ let requestID = requestAnimationFrame(() => { ...})

+ destructorMethodDeclaration() {

...

+ cancelAnimationFrame(requestID)

+ }

  • requestAnimationFrame() for creating animations
  • Usually called recursively
  • Can execute even after component destruction

Fix Pattern

Leak Pattern

32 of 49

4. Unreleased Subscription

32

{

observer1.subscribe(() => {...})

}

{

observer1

+ .pipe(takeUntil(observer2))

.subscribe(() => {...})

+ destructorMethodDeclaration() {

...

+ observer2.next()

+ observer2.complete()

+ }

}

  • Keeps piling up new observables on each component mount
  • Most common in Angular

Leak Pattern

Fix Pattern

33 of 49

5a. Component instance event listeners (Vue only)

33

...

this.$on(event, callback);

...

...

this.$on(event, callback);

...

+ destructorMethodDeclaration() {

+ this.$off(event, callback);

+ }

Fix Pattern

Leak Pattern

34 of 49

5b. Root instance event listeners (Vue only)

34

...

this.root.$on(event, callback);

...

...

this.root.$on(event, callback);

...

+ destructorMethodDeclaration() {

+ this.root.$off(event, callback);

+ }

Fix Pattern

Leak Pattern

35 of 49

5c. Unremoved Event bus (Vue only)

35

import EventBus from ’../EventBus’;

...

EventBus.$on(event, callback);

...

import EventBus from ’../EventBus’;

...

EventBus.$on(event, callback);

...

+ destructorMethodDeclaration() {

+ EventBus.$off(event, callback);

+ }

Fix Pattern

Leak Pattern

  • Event bus created & emitted in one component
  • Listened in another component

36 of 49

Coverage of Selected Patterns

36

  • 102 out of 124 (82%) in React.
  • 57 out of 65 (88%) in Angular.
  • 32 out of 40 (80%) in Vue.

37 of 49

Applying Fix Patterns

37

SPA project

Identify JS file(s)

Transform to AST

Find leak pattern matches

Match found?

Apply fix to AST

Yes

Convert back to source

38 of 49

EVALUATION

38

39 of 49

Research Questions

RQ1. Effectiveness How effective is the tool at minimizing memory leaks?

RQ2. Acceptance How useful are generated patches, as perceived by developers?

RQ3. Correctness What is the impact of our tool on test suite execution results?

39

40 of 49

Subjects

40

Known leaks Leaks already detected and fixed by developers.

Unknown leaks Leaks developers were not aware of.

30 open source SPA projects with already known memory leaks.

30 projects with unfound leaks at the time of evaluation

41 of 49

41

Effectiveness Evaluation (RQ 1)

Compare before and after footprints

Execute Memlab (10 Iterations)

Note memory footprints

SPA subject

LEAKPAIR

Execute LeakPair

Run the SPA Subject

Scenario file (10 Loops)

Note memory footprints again

42 of 49

42

Effectiveness Evaluation (RQ 1)

Compare before and after footprints

Execute Memlab (10 Iterations)

Note memory footprints

SPA subject

LEAKPAIR

Execute LeakPair

Run the SPA Subject

Scenario file (10 Loops)

Note memory footprints again

43 of 49

43

Compare before and after footprints

Acceptance Evaluation (RQ 2)

Is heap size or leak count reduced?

Yes

Is unknown leak?

Yes

Submit fix as PR

Track PR status

44 of 49

44

Correctness Evaluation (RQ 3)

Execute test suite

(If available)

SPA subject

LEAKPAIR

Execute LeakPair

Run the SPA Subject

Note build/ compile time

Note passing/failing test cases

Note build/compile time and test case results again

Compare before and after test cases results and execution times

45 of 49

RESULTS

45

46 of 49

Effectiveness (RQ 1)

  • 24 of 30 subjects with unknown leaks had significant heap reductions (up to 18%).
  • 6 of 30 subjects with known leaks had noticeable heap reductions. (up to 45.3%)
  • All subjects had memory leak reductions.

46

LeakPair’s patches can successfully prevent leaks and reduce heap, without leak detection.

47 of 49

Acceptance (RQ 2)

  • Total = 32 pull requests

  • Agreed = 16 (50%)

47

Merged

Approved

Improved

Ignored

12

3

1

16

LeakPair’s patches are acceptable to developers, with half of patch suggestions being accepted.

48 of 49

Correctness (RQ 3)

  • Successful build/compilation

  • Test cases of 39 of 40 subjects unchanged

  • Execution times before and after LeakPair execution shared the same range for all 40 projects.

48

The patches are non-intrusive; they neither break functionality, nor incur execution time delays.

49 of 49

Summary

49