Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability:...

95
Moving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER 14, 2017

Transcript of Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability:...

Page 1: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Moving Fast with High Reliability: Program Analysis at Uber

Manu Sridharan

Software Reliability Workshop

ETH Zurich

OCTOBER 14, 2017

Page 2: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Uber Apps

Rider Driver Eats

iOS and Android

Page 3: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Uber Apps

Rider Driver Eats

iOS and Android

Page 4: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rider crash: can’t get home

Driver crash: can’t earn

Using our apps involves a payment

Apps take significant time to patch

Uber cares a lot about reliability

Page 5: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

“Transportation as reliable as running water, everywhere, for everyone”

Page 6: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Hundreds of developers working simultaneously• Hundreds of commits per day

Millions of lines of code

Goal: Let builders build• Let developers stay in the flow• Let developers work independently

Uber needs to move fast

Page 7: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

How can Uber move fast and keep reliability high?

Page 8: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Modularity in Design and Analysis

Page 9: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

App design emphasizes modularity• Features can be developed and disabled independently• Enables developers to move fast

Modularity in Design and Analysis

Page 10: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

App design emphasizes modularity• Features can be developed and disabled independently• Enables developers to move fast

Analysis can both enforce and leverage design• Leverage code modularity for greater scalability / precision• Modular analysis avoids pollution from unrelated code

Modularity in Design and Analysis

Page 11: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

App design emphasizes modularity• Features can be developed and disabled independently• Enables developers to move fast

Analysis can both enforce and leverage design• Leverage code modularity for greater scalability / precision• Modular analysis avoids pollution from unrelated code

Strong willingness to adjust design to help analysis

Modularity in Design and Analysis

Page 12: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Remainder of this talk

Page 13: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Designing for analyzability

Remainder of this talk

Page 14: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Case studiesDesigning for analyzability

Remainder of this talk

Page 15: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Case studiesDesigning for analyzability

Future projects / open problems

Remainder of this talk

Page 16: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Designing for Analyzability

Page 17: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

In 2016, Uber built new rider apps from scratch

Key goals included:• High availability of core flows, without

slowing feature development• Maximal decoupling of features

These goals help static analysis!

Rewritten Rider App

Page 18: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Plugins

Page 19: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Isolate core flows from other features• Core flow: getting a ride• Non-core: account settings

Plugins can be disabled remotely• Reduces risk in feature experimentation

Plugins: Motivation

Page 20: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Plugin examples

Feed

Locationshortcuts

Scheduledrides

Profiles

Page 21: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Core code defines plugin points• Changes get extra manual review

Core can only reference non-core via plugins• Enforced via naming conventions + linting

80% of code in plugins

Core flows tested with all plugins disabled

Plugins: Under the Hood

Page 22: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Deep Scope Hierarchies

Page 23: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Scoping of app state

Page 24: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Some state needs to be shared between features• The map• User account information when logged in

Scoping of app state

Page 25: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Some state needs to be shared between features• The map• User account information when logged in

Storing in global state leads to bugs• Subtle dependencies creep in between features

Scoping of app state

Page 26: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Some state needs to be shared between features• The map• User account information when logged in

Storing in global state leads to bugs• Subtle dependencies creep in between features

Must manage object lifetimes carefully to avoid leaks• E.g., after trip, need to promptly discard trip state• In old app, fragile reset() methods

Scoping of app state

Page 27: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Deep Scope Hierarchies

Page 28: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Deep Scope HierarchiesRoot

Page 29: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Deep Scope HierarchiesRoot

LoggedOut

Page 30: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Deep Scope HierarchiesRoot

LoggedOut LoggedIn

Page 31: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Deep Scope HierarchiesRoot

LoggedOut LoggedIn

Request

Page 32: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Deep Scope HierarchiesRoot

LoggedOut LoggedIn

Request OnTrip

Page 33: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Parent creates / destroys child scopes

Deep Scope HierarchiesRoot

LoggedOut LoggedIn

Request OnTrip

Page 34: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Parent creates / destroys child scopes

State must be explicitly shared from parent to child• Statically prohibited from accessing sibling state

Deep Scope HierarchiesRoot

LoggedOut LoggedIn

Request OnTrip

Page 35: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Parent creates / destroys child scopes

State must be explicitly shared from parent to child• Statically prohibited from accessing sibling state

Deep Scope HierarchiesRoot

LoggedOut LoggedIn

Request OnTrip

Page 36: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Parent creates / destroys child scopes

State must be explicitly shared from parent to child• Statically prohibited from accessing sibling state

Object lifetimes tied to scopes• No more reset() methods• Helps prevent leaks

Deep Scope HierarchiesRoot

LoggedOut LoggedIn

Request OnTrip

Page 37: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Parent creates / destroys child scopes

State must be explicitly shared from parent to child• Statically prohibited from accessing sibling state

Object lifetimes tied to scopes• No more reset() methods• Helps prevent leaks

Based on new RIB framework• Router-Interactor-Builder (refinement of MVC)• Builders manage state sharing, Routers manage tree structure

Deep Scope HierarchiesRoot

LoggedOut LoggedIn

Request OnTrip

Page 38: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Implications

Page 39: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Features stay independent• A challenge with so much shared app state

Well-defined contracts• Between features, via RIB tree• Between core and optional code, via plugins

Result: developers stay sane

Decoupling: Good for Moving Fast

Page 40: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Decoupling: Good for Analysis!

Page 41: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Better whole program analysis• Less pollution from imprecise data flow

Decoupling: Good for Analysis!

Page 42: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Better whole program analysis• Less pollution from imprecise data flow

Modular verification!• Of core code, via plugins• Of individual features, via deep scopes

Decoupling: Good for Analysis!

Page 43: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Better whole program analysis• Less pollution from imprecise data flow

Modular verification!• Of core code, via plugins• Of individual features, via deep scopes

May require specifications at boundaries• Can we infer them?

Decoupling: Good for Analysis!

Page 44: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Better whole program analysis• Less pollution from imprecise data flow

Modular verification!• Of core code, via plugins• Of individual features, via deep scopes

May require specifications at boundaries• Can we infer them?

Big opportunity!

Decoupling: Good for Analysis!

Page 45: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Nullness Checking for Android

Page 46: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Principles for bug checkers

Page 47: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

All reports must be addressed.Precision is critical

Block the build

Principles for bug checkers

Page 48: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

All reports must be addressed.Precision is critical

Block the build

Principles for bug checkers

Aim for instant IDE feedback.Performance is critical

Run checks early

Page 49: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

All reports must be addressed.Precision is critical

Block the build

Principles for bug checkers

Aim for instant IDE feedback.Performance is critical

Run checks early

Makes errors more understandable, analyses more performant

Annotations are OK

Page 50: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Major source of Android app crashes

In mid-2015, Facebook released Infer (http://fbinfer.com/), with static detection of NPEs

Uber aggressively adopted Infer to “eradicate” NPEs

NullPointerException Background

Exception in thread "main" java.lang.NullPointerException at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.visit(JDTJava2CAstTranslator.java:1480) at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.visitNode(JDTJava2CAstTranslator.java:2901) at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.visit(JDTJava2CAstTranslator.java:1462) at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.visitNode(JDTJava2CAstTranslator.java:2887) at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.visitNodeOrNodes(JDTJava2CAstTranslator.java:2959) at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.createBlock(JDTJava2CAstTranslator.java:1275) at com.ibm.wala.cast.java.translator.jdt.JDTJava2CAstTranslator.visit(JDTJava2CAstTranslator.java:1280) …

Page 51: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Type-Based NPE Prevention

Page 52: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Type-Based NPE Prevention

static void log(Object x) { System.out.println(x.toString()); } static void foo() { log(null); }

Page 53: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Type-Based NPE Prevention

static void log(Object x) { System.out.println(x.toString()); } static void foo() { log(null); }

Error: cannot pass null to @NonNull parameter x

Page 54: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Type-Based NPE Prevention

static void log(@Nullable Object x) { System.out.println(x.toString()); } static void foo() { log(null); }

Page 55: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Type-Based NPE Prevention

static void log(@Nullable Object x) { System.out.println(x.toString()); } static void foo() { log(null); }

Error: de-referencing x may yield NPE

Page 56: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Type-Based NPE Prevention

static void log(@Nullable Object x) { if (x == null) return; System.out.println(x.toString()); } static void foo() { log(null); }

Page 57: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Type-Based NPE Prevention

static void log(@Nullable Object x) { if (x == null) return; System.out.println(x.toString()); } static void foo() { log(null); } 👍

Page 58: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Type-Based NPE Prevention

static void log(@Nullable Object x) { if (x == null) return; System.out.println(x.toString()); } static void foo() { log(null); } 👍

As in Eradicate (http://fbinfer.com/docs/eradicate.html),

Checker Framework (https://checkerframework.org/)

Page 59: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Eradicate: huge success, but significant running time• Only ran on submit queue (final stage of CI)

Error Prone (http://errorprone.info/): custom checkers within Java compiler

Efficient: Re-use work that compiler has already done• E.g., AST construction, type analysis

NullAway: Eradicate-like checking in Error Prone

NullAway

Page 60: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Runs on all builds instead of just submit queue• < 10% overhead• Devs get much faster feedback

Found hundreds of new issues• Greater flexibility in handling third-party jars

Open source! https://github.com/uber/NullAway

Experience with NullAway

Page 61: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Analysis is not sound• Not even soundy! (http://soundiness.org)• Contrast with Checker Framework

Holes: multithreading, initialization, arrays, mutation, …

In practice, gaps have been in library models

RAVE (https://github.com/uber-common/rave) ensures nullness assumptions valid for data from disk/network

Soundness?

Page 62: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Recent enhancement: stream handling

Page 63: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Recent enhancement: stream handling

class Data { int age() { ... }; } class Person { @Nullable Data data() { ... }; } Stream<Person> pplStream = ...; int ageSum = pplStream .filter((p) -> p.data() != null) .mapToInt((p) -> p.data().age()) .sum();

Page 64: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Recent enhancement: stream handling

class Data { int age() { ... }; } class Person { @Nullable Data data() { ... }; } Stream<Person> pplStream = ...; int ageSum = pplStream .filter((p) -> p.data() != null) .mapToInt((p) -> p.data().age()) .sum();

Error: de-referencing p.data() may yield NPE

Page 65: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Recent enhancement: stream handling

class Data { int age() { ... }; } class Person { @Nullable Data data() { ... }; } Stream<Person> pplStream = ...; int ageSum = pplStream .filter((p) -> p.data() != null) .mapToInt((p) -> p.data().age()) .sum();

Result: Stream<{ p | p.data() != null}>

Page 66: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Recent enhancement: stream handling

class Data { int age() { ... }; } class Person { @Nullable Data data() { ... }; } Stream<Person> pplStream = ...; int ageSum = pplStream .filter((p) -> p.data() != null) .mapToInt((p) -> p.data().age()) .sum();

Result: Stream<{ p | p.data() != null}>

👍

Page 67: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Multithreading

Page 68: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Multithreading

Page 69: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Many nasty bugs possible• Data races• Accessing UI off main thread

Multithreading

Page 70: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Many nasty bugs possible• Data races• Accessing UI off main thread

Most multithreading via ReactiveX• Functional reactive programming for asynchronous

streams• Very structured use of threads

Multithreading

Page 71: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Many nasty bugs possible• Data races• Accessing UI off main thread

Most multithreading via ReactiveX• Functional reactive programming for asynchronous

streams• Very structured use of threads

Multithreading

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .observeOn(MAIN) .subscribe(i -> display(i));

Page 72: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Many nasty bugs possible• Data races• Accessing UI off main thread

Most multithreading via ReactiveX• Functional reactive programming for asynchronous

streams• Very structured use of threads

Opportunity: specialized analyses!

Multithreading

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .observeOn(MAIN) .subscribe(i -> display(i));

Page 73: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

Page 74: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

Off-main-thread UI access

Page 75: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

@UIEffect void display(i) { … }

Page 76: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

@UIEffect void display(i) { … }

@UIEffect

Page 77: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

@UIEffect void display(i) { … }

Enforced with effect analysis (Gordon et al., ECOOP’13)@UIEffect

Page 78: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

@UIEffect void display(i) { … }

Enforced with effect analysis (Gordon et al., ECOOP’13)@UIEffect

Thread types for Observables (Checker Framework)

Page 79: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

@UIEffect void display(i) { … }

Enforced with effect analysis (Gordon et al., ECOOP’13)

@MainThread

@UIEffect

Thread types for Observables (Checker Framework)

Page 80: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

@UIEffect void display(i) { … }

Enforced with effect analysis (Gordon et al., ECOOP’13)

@MainThread@ComputeThread

@UIEffect

Thread types for Observables (Checker Framework)

Page 81: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

@UIEffect void display(i) { … }

Enforced with effect analysis (Gordon et al., ECOOP’13)

@MainThread@ComputeThread@ComputeThread

@UIEffect

Thread types for Observables (Checker Framework)

Page 82: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

@UIEffect void display(i) { … }

Enforced with effect analysis (Gordon et al., ECOOP’13)

@MainThread@ComputeThread@ComputeThread

@UIEffect

Thread types for Observables (Checker Framework)

Error: UI effect off main thread

Page 83: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Rx Thread Checker

sourceObservable() .observeOn(COMPUTATION) .map(x -> expensive(x)) .subscribe(i -> display(i));

@UIEffect void display(i) { … }

Enforced with effect analysis (Gordon et al., ECOOP’13)

@MainThread@ComputeThread@ComputeThread

@UIEffect

Thread types for Observables (Checker Framework)

Error: UI effect off main thread

Actively deploying across Android codebase

Future work: extend to enforce side-effect freedom

Page 84: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Other projects / open problems

Page 85: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Performance: Speed and Memory

Micromax Spark

Page 86: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Need to run smoothly on all devices• Many low-end devices in growth markets

Performance: Speed and Memory

Micromax Spark

Page 87: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Need to run smoothly on all devices• Many low-end devices in growth markets

How to attack with analysis?• Statically detect slow code on main thread• Give visibility into UI-blocking network requests• Reduce OutOfMemoryErrors (statically enforce scope hierarchies)

Performance: Speed and Memory

Micromax Spark

Page 88: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Need to run smoothly on all devices• Many low-end devices in growth markets

How to attack with analysis?• Statically detect slow code on main thread• Give visibility into UI-blocking network requests• Reduce OutOfMemoryErrors (statically enforce scope hierarchies)

A challenge with new features going in constantly!

Performance: Speed and Memory

Micromax Spark

Page 89: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Future of iOS development

Uber has invested heavily• New rider app written entirely in Swift• Google “swift with a hundred engineers”• Same architecture! Plugins + deep scopes + Rx

Little analysis infrastructure available• We released NEAL for linting: https://github.com/uber/NEAL

Cross-platform analyses? Swift-specific?

Infrastructure: Swift

Page 90: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Verification of startup code

Preventing code duplication

Test generation / selection

Dead code elimination

And more…

Page 91: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Need high app reliability

Need developers to move fast

Approach: modular app design + program analysis• Analysis helps enforce design • Design increases analysis effectiveness• Tons of opportunities

Conclusions

Page 92: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Blog postsApp architecture: https://eng.uber.com/new-rider-app/Scope hierarchies: https://eng.uber.com/deep-scope-hierarchies/Plugins: https://eng.uber.com/plugins/

Open sourceNullAway: https://github.com/uber/NullAwayNEAL: https://github.com/uber/NEAL

Relevant resources

Page 93: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

Uber Programming Systems Group

Raj Barik Lazaro Clapp Murali KrishnaRamanathan

ManuSridharan

Adam Welc Benno Stein (Intern)

Page 94: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER

First & Last NameThank you

Page 95: Moving Fast with High Reliability: Program Analysis at UberMoving Fast with High Reliability: Program Analysis at Uber Manu Sridharan Software Reliability Workshop ETH Zurich OCTOBER