One of the major difficulties in debugging concurrent programs is that the programmer usually experiences frequent thread context switches, which perplexes the reasoning process. This problem can be alleviated by trace simplification techniques, which produce the same computation process but with much fewer number of context switches. The state of the art trace simplification technique takes a dynamic approach and does not scale well to large traces, hampering its practicality. We present a static trace simplification approach, SimTrace, that dramatically improves the efficiency of trace simplification through reasoning about the computation equivalence of traces offline. By constructing a dependence graph model of events, our trace simplification algorithm scales linearly to the trace size and quadratic to the number of nodes in the dependence graph. Underpinned by a trace equivalence theorem, we guarantee that the results generated by SimTrace are sound and no dynamic program re-execution is required to validate the trace equivalence. Our experiments show that SimTrace scales well to traces with more than 1M events, making it attractive to practical use.
Contents:
This section shows how to use SimTrace.
package example; public class Example { public static void main (String [] args) { String url="key1=Alice&key2=Bob"; URLParse urlparse = new URLParse(url); Thread t1 = new ExampleThread(urlparse ,"key1"); Thread t2 = new ExampleThread(urlparse ,"key2"); System.out.println("before parsing: "+urlparse.getURL()); t2.start (); t1.start(); try { t1.join(); t2.join(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("after parsing: "+urlparse.getURL()); } } |
package example; public class ExampleThread extends Thread { URLParse urlparse; String key; ExampleThread(URLParse url,String key){ this.urlparse = url; this.key = key; } public void run() { try{ urlparse.parse(key); }catch(Exception e) { e.printStackTrace(); System.exit(1); } } } |
package example; public class URLParse { private String url; URLParse (String url) { this.url=url; } //should be synchronized public void parse(String key) { String val = getVal(key); if(val.equals("Alice")) replaceVal(key,"A"); if(val.equals("Bob")) replaceVal(key,"B"); } private void replaceVal(String key, String newVal) { int keyPos=url.indexOf(key); int valPos=url.indexOf("=", keyPos)+1; int ampPos=url.indexOf("&", keyPos); if(ampPos<0) ampPos = url.length(); url=url.substring(0, valPos) +newVal+url.substring(ampPos); } private String getVal(String key) { int keyPos=url.indexOf(key); int valPos=url.indexOf("=", keyPos)+1; int ampPos=url.indexOf("&", keyPos); if(ampPos<0) ampPos=url.length(); return url.substring(valPos,ampPos); } public String getURL() { return url; } } |
javac ./app/example/*.java |
java -cp ./app/:simtrace-instrumentor.jar edu.hkust.clap.Main example.Example |
rm -rf ./tmp/*/edu |
java -cp ./tmp/runtime/:simtrace-monitor.jar edu.hkust.clap.Main example.Example |
java -cp simtrace-engine.jar edu.hkust.clap.engine.SimTraceMain |
Number of Threads: 3 Number of Shared Variables: 1 Number of Lock Nodes: 0 Number of Message Nodes: 8 Number of Non-Method Entry/Exit Nodes: 33 Number of Read/Write Nodes: 25 Number of Total Nodes: 61 Number of Original Context Switches: 12 Number of Simplified Context Switches: 5 Number of Nodes In the Original Graph: 6 Number of Edges In the Original Graph: 10 Total Data Load Time: 30 ms Total Graph Construction Time: 3 ms Total Graph Merging Time: 0 ms Total Graph Topological Sort Time: 0 ms Total Schedule Generation Time: 3 ms Total Processing Time: 37 ms |
javac -cp ./tmp/replay/:simtrace-replayer.jar ./src/replaydriver/ReplayDriver.java |
java -cp ./src/:./tmp/replay/:simtrace-replayer.jar replaydriver.ReplayDriver |
We have evaluated SimTrace using several popular multi-threaded subjects as well as a number of large multi-threaded Java applications. SimTrace is able to efficiently and significantly simplify the trace.
Program | LOC | Thread | SV | Trace Size | Time | Old Ctxt | New Ctxt | Reduction |
---|---|---|---|---|---|---|---|---|
Philosopher | 81 | 6 | 1 | 131 | 6ms | 51 | 18 | 65% |
Bubble | 417 | 26 | 25 | 1,493 | 23ms | 454 | 163 | 71% |
Elevator | 514 | 4 | 13 | 2,104 | 8ms | 80 | 14 | 83% |
TSP | 709 | 5 | 234 | 636,499 | 149s | 9272 | 1337 | 86% |
Cache4j | 3,897 | 4 | 5 | 1,225,167 | 592s | 417 | 33 | 92% |
Weblench | 35,175 | 3 | 26 | 11,630 | 57ms | 156 | 24 | 85% |
OpenJMS | 154,563 | 32 | 365 | 376,187 | 38s | 96,643 | 11,402 | 88% |
Jigsaw | 381,348 | 10 | 126 | 19,074 | 130ms | 2396 | 65 | 97% |