reentrancer fse

Upload: msridhar2422

Post on 30-May-2018

228 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/9/2019 Reentrancer FSE

    1/30

    IBM Research

    2009 IBM Corporation

    Refactoring for Reentrancy

    Jan Wloka Manu Sridharan, Frank Tip

    IBM Rational IBM Research

    ESEC / FSE 2009

  • 8/9/2019 Reentrancer FSE

    2/30

    IBM Research

    2009 IBM Corporation

    Vision: A Migration Path to Multicores

    2

    Legacy Single-Threaded App

    App Safe for Multicore(just embarrassing parallelism)

    App Optimized for Multicore(finer-grained concurrency,

    reduced contention, etc.)

    Correctness before performance

    Current

    work

  • 8/9/2019 Reentrancer FSE

    3/30

    IBM Research

    2009 IBM Corporation

    Challenge: Lack of Reentrancy

    Definition of reentrant program

    distinct program executions do not

    affect each other, sequentially or concurrently

    Mutable global statethe key barrier to reentrancy

    3

  • 8/9/2019 Reentrancer FSE

    4/30

    IBM Research

    2009 IBM Corporation

    Running Example of Non-Reentrancy

    class Config {

    static final Map conInfo = new HashMap();

    static void setOption(String name, String value) {

    conInfo.put(name, value);

    }

    static String getOption(String name) {return conInfo.get(name);

    }

    }

    test1() { Config.setOption(foo, bar); }

    test2() { assert Config.getOption(foo) == null; }

    4

    Problem:test2fails if run after test1, but passes if run alone

    Race conditionsonconInfoif tests run in parallel

    Mutable global state

  • 8/9/2019 Reentrancer FSE

    5/30

    IBM Research

    2009 IBM Corporation

    Existing Approaches to Reentrancy

    Approach # 1:get rid of mutable global state

    A possible solution for new projects

    But, for existing code, too intrusive and hard to automate

    Approach # 2:separate OS processes / classloaders

    Strong isolation between executions

    But, further optimization difficult (e.g., adding shared state)

    5

  • 8/9/2019 Reentrancer FSE

    6/30

    IBM Research

    2009 IBM Corporation

    Our Approach: Thread-Local State

    Idea: Replace all mutable globals with thread-local variables

    Implicit per-thread copy of each variable

    Available on most threading platforms (Java, pthreads, etc.)Result: code is reentrant if executions run in fresh threads

    Key advantage:enables local optimizations

    Selectively replace thread locals with shared state + locking

    Correctness before performance

    Challenge: handling real-world language / programs

    In particular, initialization and library usage

    6

  • 8/9/2019 Reentrancer FSE

    7/30

    IBM Research

    2009 IBM Corporation

    Contributions

    Reentrancer Design

    Goal:practical tool for real-world programs

    Mostly automated

    Targets Java, but applicable to other languages

    Reentrancer Implementation and Evaluation

    Runs on realistic benchmarks (up to 83 KLOC)

    Fixed observed reentrancy issues

    Enabled parallel speedup for 3 of 5 benchmarks

    7

  • 8/9/2019 Reentrancer FSE

    8/30

    IBM Research

    2009 IBM Corporation

    Reentrancer Phases

    1. Check preconditions

    a) Detect potential violations(automatic)

    b) Inspect / fix warnings (manual)

    2. Make code reentrant (automatic)

    a) Encapsulate mutable global state

    b) Introduce lazy initialization

    c) Introduce thread locals

    3. Create fresh thread per execution (manual)

    8

  • 8/9/2019 Reentrancer FSE

    9/30

    IBM Research

    2009 IBM Corporation

    Preconditions 1: Static Initialization

    Issue: thread locals must be initialized as globals were

    Challenge: initializers can have complex and fragile behavior

    class A { static final intx = B.y + 1; }class B { static final inty = A.x + 2; }

    Solution: change toexplicit lazy initialization

    Makes thread-local introduction a separate, simple phase

    Notbehavior preserving for fragile dependences like above

    Precondition check warns if behavior may change

    Indicates badness in general

    9

  • 8/9/2019 Reentrancer FSE

    10/30

    IBM Research

    2009 IBM Corporation

    Preconditions 2: Library Usage

    Issue: Library usage can break reentrancy (e.g., file I/O)

    Challenges

    1. Cannot refactor library code2. Hard to detect all non-reentrant library routines

    Solution:warn about calls to blacklisted methods

    Doesnt require expensive whole-program analysis

    Catches most common cases

    Always double-check with test suite!

    10

  • 8/9/2019 Reentrancer FSE

    11/30

    IBM Research

    2009 IBM Corporation

    Running Example

    class Config {

    private static final Map conInfo = new HashMap();

    private static final String versionStr = 2.0;

    static {

    conInfo.put(version, versionStr);

    }

    static void setOption(String name, String value) {

    System.out.println(name + : + value);

    conInfo.put(name, value);

    }

    static String getOption(String name) {

    return conInfo.get(name);

    }

    }

    11

  • 8/9/2019 Reentrancer FSE

    12/30

    IBM Research

    2009 IBM Corporation

    Step 1(a): Detect Violations (automatic)

    class Config {

    private static final Map conInfo = new HashMap();

    private static final String versionStr = 2.0;

    static {

    conInfo.put(version, versionStr);

    }

    static void setOption(String name, String value) {

    System.out.println(name + : + value);

    conInfo.put(name, value);

    }

    static String getOption(String name) {

    return conInfo.get(name);}

    }

    12

  • 8/9/2019 Reentrancer FSE

    13/30

    IBM Research

    2009 IBM Corporation

    Step 1(b): Fix Warnings (manual)

    class Config {

    private static final Map conInfo = new HashMap();

    private static final String versionStr = 2.0;

    static {

    conInfo.put(version, versionStr);

    }

    static void setOption(String name, String value) {

    // System.out.println(name + : + value);

    conInfo.put(name, value);

    }

    static String getOption(String name) {

    return conInfo.get(name);}

    }

    13

  • 8/9/2019 Reentrancer FSE

    14/30

    IBM Research

    2009 IBM Corporation

    Step 2(a):Encapsulate Mutable Globals(automatic)

    class Config {

    private static final Map conInfo = new HashMap();

    private static final String versionStr = 2.0;

    static {

    conInfo.put(version, versionStr);

    }

    static void setOption(String name, String value) {

    conInfo.put(name, value);

    }

    static String getOption(String name) {

    return conInfo.get(name);

    }}

    14

  • 8/9/2019 Reentrancer FSE

    15/30

    IBM Research

    2009 IBM Corporation

    Step 2(a): Encapsulate Mutable Globals(automatic)

    class Config {

    private static final Map conInfo = new HashMap();

    private static final String versionStr = 2.0;

    static Map getConInfo() {

    return conInfo;

    }

    static {

    getConInfo().put(version, versionStr);

    }

    static void setOption(String name, String value) {

    getConInfo().put(name, value);

    }static String getOption(String name) {

    return getConInfo().get(name);

    }

    }

    15

  • 8/9/2019 Reentrancer FSE

    16/30

    IBM Research

    2009 IBM Corporation

    On Mutability

    If state is immutable, no need to transform

    Immutable means deeply immutable [Tschantz&Ernst,

    OOPSLA05]

    all abstract state of object

    final is not enough

    Simple type-based analysis to detect immutability

    16

  • 8/9/2019 Reentrancer FSE

    17/30

    IBM Research

    2009 IBM Corporation

    Step 2(b): Introduce Lazy Initialization (automatic)

    class Config{

    private static Map conInfo = new HashMap();

    private static final String versionStr = 2.0;

    static Map getConInfo() {

    return conInfo;

    }

    static {

    getConInfo().put(version, versionStr);

    }

    17

  • 8/9/2019 Reentrancer FSE

    18/30

    IBM Research

    2009 IBM Corporation

    Step 2(b): Introduce Lazy Initialization (automatic)

    class Config {

    private static Map conInfo;

    private static final String versionStr = 2.0;

    static Map getConInfo() {

    lazyInit(); return conInfo;

    }

    static booleaninitRun = false;

    static void lazyInit() {

    if (!initRun) {

    initRun = true;

    conInfo = new HashMap();

    getConInfo().put(version, versionStr);}

    }

    18

  • 8/9/2019 Reentrancer FSE

    19/30

    IBM Research

    2009 IBM Corporation

    Step 2(c): Introduce Thread Locals (automatic)

    class Config {

    private static Map conInfo;

    private static final String versionStr = 2.0;

    static Map getConInfo() {

    lazyInit(); return conInfo;

    }

    static booleaninitRun = false;

    static void lazyInit() {

    if (!initRun) {

    initRun = true;

    conInfo = new HashMap();

    getConInfo().put(version, versionStr);}

    }

    19

  • 8/9/2019 Reentrancer FSE

    20/30

    IBM Research

    2009 IBM Corporation

    Step 2(c): Introduce Thread Locals (automatic)

    class Config {

    static ThreadLocalconInfo = new ThreadLocal();

    private static final String versionStr = 2.0;

    static Map getConInfo() {

    lazyInit(); return conInfo.get();

    }

    static ThreadLocalinitRun =

    new ThreadLocal();

    static void lazyInit() {

    if (!initRun.get()) {

    initRun.set(true);

    conInfo.set(newHashMap());getConInfo().put(version, versionStr);

    }

    }

    }

    20

  • 8/9/2019 Reentrancer FSE

    21/30

    IBM Research

    2009 IBM Corporation

    Step 3: Create Fresh Thread per Execution (manual)

    test1() { Config.setOption(foo, bar); }

    test2() { assert Config.getOption(foo) == null; }

    21

    test1() {

    runInFreshThread(newRunnable() { public void run() {

    Config.setOption(foo, bar);

    } });

    }

    test2() {

    runInFreshThread(newRunnable() { public void run() {assert Config.getOption(foo) == null;

    } });

    }

  • 8/9/2019 Reentrancer FSE

    22/30

    IBM Research

    2009 IBM Corporation

    Experiments: Implementation

    22

    Precondition Checker

    Built on WALA (http://wala.sf.net)

    Emits warnings for violations

    Code Refactoring

    Extension to Eclipse JDT

    Handles many Java corner cases

    (interface fields, boxing/unboxing)

  • 8/9/2019 Reentrancer FSE

    23/30

    IBM Research

    2009 IBM Corporation

    Experiments: Methodology

    Five single-threaded benchmarks, up to 83 KLOC

    For each benchmark:

    1. Establish reentrancy problem(s)2. Inspect / fix precondition check warnings

    3. Run refactoring

    4. Ensure test suite passes

    5. Ensure reentrancy problem(s) fixed

    6. Measure performance

    23

  • 8/9/2019 Reentrancer FSE

    24/30

    IBM Research

    2009 IBM Corporation

    Experiments: Key Questions

    1. Precondition violations

    a) How many?

    b) How many false positives?

    2. How much code is changed by refactoring?

    3. Performance of running test suite

    a) Before vs. after on one core?

    b) Before vs. after on two cores?

    24

  • 8/9/2019 Reentrancer FSE

    25/30

    IBM Research

    2009 IBM Corporation

    Results: Precondition Violation Warnings

    0

    20

    40

    60

    80

    100

    120

    140

    coco/r xml-security bcel javacc wala

    Library

    Init False

    Init True

    False positives due to weak immutability inference

    Most warnings benign

    25

  • 8/9/2019 Reentrancer FSE

    26/30

    IBM Research

    2009 IBM Corporation

    Results: Code Churn

    26

    0

    1

    2

    3

    4

    5

    6

    7

    8

    coco/r x l-security cel javacc ala

    KLOC changed

  • 8/9/2019 Reentrancer FSE

    27/30

    IBM Research

    2009 IBM Corporation

    Results: Test Suite Runtime After Refactoring

    0

    0.2

    0.4

    0.6

    0.81

    1.2

    1.4

    1.6

    1.8

    2

    coco/r xml-security bcel javacc wala

    One Core

    Two Cores

    Parallel speedup for 3 of 5 benchmarks

    coco/r anomaly: removed fresh class loaders27

  • 8/9/2019 Reentrancer FSE

    28/30

    IBM Research

    2009 IBM Corporation

    Related Work

    Refactoring tojava.util.concurrent[DME09]

    Cilk++ hyperobjects [FHLL09]

    Java immutability [TE05,ZPAAKE07,QTE08]

    28

  • 8/9/2019 Reentrancer FSE

    29/30

    IBM Research

    2009 IBM Corporation

    Conclusions

    Reentrancy viachanging globals to thread-locals

    Correctness before performance

    Prototype implementation works and enablesparallel speedups

    Future work

    Better immutability inference

    More incremental workflow

    29

  • 8/9/2019 Reentrancer FSE

    30/30

    IBM Research

    2009 IBM Corporation30

    Thanks!