Download as pdf or txt
Download as pdf or txt
You are on page 1of 51

A Dataflow Language for Scripted Debugging

Guillaume Marceau,
Greg Cooper,
Shriram Krishnamurthi,
Steven Reiss

Brown University

Automated Software Engineering, September 2004

1
plt­scheme.org
The Bug
2 1 1 1
class ShortestPathSolver {
  
2 2
  public HashMap backtrace = new HashMap();
  private PriorityQueue q = new PriorityQueue();

  public ShortestPathSolver(DirectedGraph graph, 
                            Node source) {
    source.weight = 0.0;
    q.addAll(graph.getNodes());

    while(!q.isEmpty()) {
      Node node = (Node)q.extractMin();
      List successors = graph.getSuccsOf(node);
      for(Iterator succIt = successors.iterator(); 
          succIt.hasNext(); )
        relax(node, (Node)succIt.next());
    }
    System.out.println("Result backtrace:\n" + 
                       backtrace.keySet());
  }

  public void relax(Node origin, Node dest) {
    double candidateWeight = 
      origin.weight + origin.distanceTo(dest);
    if (candidateWeight < dest.weight) {
      dest.weight = candidateWeight;
      backtrace.put(dest, origin);
    }
  }
}
 
2
plt­scheme.org
The Bug
2 1 1 1
class ShortestPathSolver {
  
2 2
  public HashMap backtrace = new HashMap();
  private PriorityQueue q = new PriorityQueue();

  public ShortestPathSolver(DirectedGraph graph, 
                            Node source) {
    source.weight = 0.0;
    q.addAll(graph.getNodes());

    while(!q.isEmpty()) {
      Node node = (Node)q.extractMin();
      List successors = graph.getSuccsOf(node);
      for(Iterator succIt = successors.iterator(); 
          succIt.hasNext(); )
        relax(node, (Node)succIt.next());
    }
    System.out.println("Result backtrace:\n" + 
                       backtrace.keySet());
  }

  public void relax(Node origin, Node dest) {
    double candidateWeight = 
      origin.weight + origin.distanceTo(dest);
    if (candidateWeight < dest.weight) {
      dest.weight = candidateWeight;
      backtrace.put(dest, origin);
    }
  }
}
 
3
plt­scheme.org
The Bug
2 1 1 1
class ShortestPathSolver {
  
2 2
  public HashMap backtrace = new HashMap();
  private PriorityQueue q = new PriorityQueue();

  public ShortestPathSolver(DirectedGraph graph, 
                            Node source) {
  
    source.weight = 0.0; Result backtrace:
    q.addAll(graph.getNodes());
  [[node 1 : distance 2],
    while(!q.isEmpty()) {    [node 2 : distance 2],
      Node node = (Node)q.extractMin();    [node 3 : distance 3]
      List successors = graph.getSuccsOf(node);
      for(Iterator succIt = successors.iterator();     [node 4 : distance inf],
          succIt.hasNext(); )    [node 5 : distance inf],
        relax(node, (Node)succIt.next());    [node 6 : distance inf]]
    }
    System.out.println("Result backtrace:\n" +   
                       backtrace.keySet());
  }

  public void relax(Node origin, Node dest) {
    double candidateWeight = 
      origin.weight + origin.distanceTo(dest);
    if (candidateWeight < dest.weight) {
      dest.weight = candidateWeight;
      backtrace.put(dest, origin);
    }
  }
}
 
4
plt­scheme.org
The Bug

class ShortestPathSolver {
  
  public HashMap backtrace = new HashMap();
  private PriorityQueue q = new PriorityQueue();

  public ShortestPathSolver(DirectedGraph graph, 
                            Node source) {
    source.weight = 0.0;
    q.addAll(graph.getNodes());

    while(!q.isEmpty()) {
      Node node = (Node)q.extractMin();
      List successors = graph.getSuccsOf(node);
      for(Iterator succIt = successors.iterator(); 
          succIt.hasNext(); )
        relax(node, (Node)succIt.next());
    }
    System.out.println("Result backtrace:\n" + 
                       backtrace.keySet());
  }

  public void relax(Node origin, Node dest) {
    double candidateWeight = 
      origin.weight + origin.distanceTo(dest);
    if (candidateWeight < dest.weight) {
      dest.weight = candidateWeight;
      backtrace.put(dest, origin);
    }
  }
}
 
5
plt­scheme.org
The Bug

class ShortestPathSolver {
  
  public HashMap backtrace = new HashMap();
  private PriorityQueue q = new PriorityQueue();

  public ShortestPathSolver(DirectedGraph graph, 
                            Node source) {
    source.weight = 0.0;
    q.addAll(graph.getNodes());

    while(!q.isEmpty()) {
      Node node = (Node)q.extractMin();
      List successors = graph.getSuccsOf(node);
      for(Iterator succIt = successors.iterator(); 
          succIt.hasNext(); )
        relax(node, (Node)succIt.next());
    }
    System.out.println("Result backtrace:\n" + 
                       backtrace.keySet());
  }

  public void relax(Node origin, Node dest) {
    double candidateWeight = 
      origin.weight + origin.distanceTo(dest);
    if (candidateWeight < dest.weight) {
      dest.weight = candidateWeight;
      backtrace.put(dest, origin);
    }
  }
}
 
6
plt­scheme.org
The Bug

class ShortestPathSolver {
  
  public HashMap backtrace = new HashMap();
  private PriorityQueue q = new PriorityQueue();

  public ShortestPathSolver(DirectedGraph graph, 
                            Node source) {
    source.weight = 0.0;
    q.addAll(graph.getNodes());

    while(!q.isEmpty()) {
      Node node = (Node)q.extractMin();
      List successors = graph.getSuccsOf(node);
      for(Iterator succIt = successors.iterator(); 
          succIt.hasNext(); )
        relax(node, (Node)succIt.next());
    }
    System.out.println("Result backtrace:\n" + 
                       backtrace.keySet());
  }

  public void relax(Node origin, Node dest) {
    double candidateWeight = 
      origin.weight + origin.distanceTo(dest);
    if (candidateWeight < dest.weight) {
      dest.weight = candidateWeight;
      backtrace.put(dest, origin);
    }
  }
}
 
7
plt­scheme.org
2 10 7 12 1 50
insert
time

8
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

9
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

10
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2

11
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7

12
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10

13
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1

14
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50

15
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

16
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

> break extractMin

17
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

> break extractMin {
    stop()
  }

18
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

> break extractMin {
    if (hasPrevious && previous > current)
      stop()
    else
      hasPrevious = true
      previous = current
      resume()
  }

19
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

> break extractMin {
    if (hasPrevious && previous > current)
      for each L in listeners
        notify(L)
    hasPrevious = true
    previous = current
    resume()
  }

> add_listener extractMin {
    stop()
  }

20
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

> break extractMin {
    if (hasPrevious && previous > current)
      for each L in listeners
        notify(L)
    hasPrevious = true
    previous = current
    resume()
  }

> add_listener extractMin {
    stop()
  }

21
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

> break extractMin {
    if (hasPrevious && previous > current)
      for each L in listeners
        notify(L)
    hasPrevious = true
    previous = current
    resume()
  }

> add_listener extractMin {
    stop()
  }

22
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

> break extractMin {
    if (hasPrevious && previous > current)
      for each L in listeners
        notify(L)
    hasPrevious = true
    previous = current
    resume()
  }

> add_listener extractMin {
    stop()
  }

23
plt­scheme.org
2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

> break extractMin {
    if (hasPrevious && previous > current)
      for each L in listeners
        notify(L)
    hasPrevious = true break extractMin {
    previous = current   count++
    resume()   print count
  }
}
> add_listener extractMin {
    stop()
  }

24
plt­scheme.org
Shortcomings of callbacks

● Require a design pattern for reuse (model-observer)

● Imposes an imperative programming style

● Multiple breakpoints may contradict each other's decisions

25
plt­scheme.org
Another point of view

2 10 7 12 1 50
insert
time
extractMin
2 7 10 1 50 12

26
plt­scheme.org
1 50 12
(define extractions
   (trace extractMin
     (bind (node) (node . jdot . weight))))

27
plt­scheme.org
1 50 12
(define extractions
   (trace extractMin
     (bind (node) (node . jdot . weight))))
(1, 50) (50, 12)
(define pairs (history­e 2 extractions))

28
plt­scheme.org
1 50 12
(define extractions
   (trace extractMin
     (bind (node) (node . jdot . weight))))
(1, 50) (50, 12)
(define pairs (history­e 2 extractions))

(50, 12)
(define violations
  (filter­e
     (match­lambda [(previous current) 
                    (previous . > . current)])
     pairs))

29
plt­scheme.org
1 50 12
(define extractions
   (trace extractMin
     (bind (node) (node . jdot . weight))))
(1, 50) (50, 12)
(define pairs (history­e 2 extractions))

(50, 12)
(define violations
  (filter­e
     (match­lambda [(previous current) 
                    (previous . > . current)])
     pairs))

(set­running! true false


  (hold true  false
    (violations . ­=> . false)))

30
plt­scheme.org
Architecture

Script Script Script

Debugger

Target FrTime

Java VM
tcp/ip DrScheme
jdwp server jdwp client

31
plt­scheme.org
1) FrTime : Define debugging operations

(define (nv violations) 
  (set­running!
    (hold true
      (violations . ­=> . false))))

32
plt­scheme.org
1) FrTime : Define debugging operations

(define (nv violations) 
  (set­running!
    (hold true
      (violations . ­=> . false))))

(define (not­in­order e)
  (filter­e
     (match­lambda [(previous current) 
                    (previous . > . current)])
     e))

33
plt­scheme.org
2) DrScheme : Interactive IDE

34
plt­scheme.org
2) DrScheme : Interactive IDE

35
plt­scheme.org
3) Scheme Libraries: Access to I/O and Graphics

36
plt­scheme.org
3) Scheme Libraries: Access to I/O and Graphics

37
plt­scheme.org
3) Scheme Libraries: Access to I/O and Graphics
(define tree­start
  (trace ((tsp . jdot . mst) . jloc . entry)
         (bind () true)))

38
plt­scheme.org
3) Scheme Libraries: Access to I/O and Graphics
(define tree­start
  (trace ((tsp . jdot . mst) . jloc . entry)
         (bind () true)))

(define tree­new­edge
  (trace ((tsp . jdot . mst) . jloc . 80)
         (bind (e) e)))

39
plt­scheme.org
3) Scheme Libraries: Access to I/O and Graphics
(define tree­start
  (trace ((tsp . jdot . mst) . jloc . entry)
         (bind () true)))

(define tree­new­edge
  (trace ((tsp . jdot . mst) . jloc . 80)
         (bind (e) e))

(define tree 
  (event­loop­b ([current­tree empty])
   
   [tree­new­edge
    =>
    (lambda (e)
      (cons (make­edge (e . jdot . v1)
                       (e . jdot . v2))
            current­tree))]

   [tree­start empty]))

40
plt­scheme.org
3) Scheme Libraries: Access to I/O and Graphics
(define tree­start
  (trace ((tsp . jdot . mst) . jloc . entry)
         (bind () true)))

(define tree­new­edge
  (trace ((tsp . jdot . mst) . jloc . 80)
         (bind (e) e)))

(define tree 
  (event­loop­b ([current­tree empty])
   
   [tree­new­edge
    =>
    (lambda (e)
      (cons (make­edge (e . jdot . v1)
                       (e . jdot . v2))
            current­tree))]

   [tree­start empty]))

(display­lines tree)

41
plt­scheme.org
Performance

Script Script Script

Debugger

Target FrTime

Java VM
tcp/ip DrScheme
jdwp server jdwp client

Time per event

Heap operations 0.002 msec  0.1%


JDWP decoding 0.783 msec 35.3%
FrTime scheduling 0.581 msec 26.2%
Script execution 0.851 msec 38.4%

Total response time 2.217 msec

42
plt­scheme.org
Related work

Based on streams: Dalek, UFO

Based on callbacks: Dispel, Acid, Deet, Parasight

Based on predicates: Coca, Path-expressions, Query-based dbg

Based on temporal-logics: Java-Mac, Java Path Explorer

43
plt­scheme.org
Future work

(define tree­start
  (trace ((tsp . jdot . mst) . jloc . entry)
         (bind () true)))

(define tree­new­edge
  (trace ((tsp . jdot . mst) . jloc . 80)
         (bind (e) e)))

44
plt­scheme.org
Future work

Breakpoint locations in term of XPath expressions

45
plt­scheme.org
Future work

Breakpoint locations in term of XPath expressions

Monitoring temporal contracts

46
plt­scheme.org
Future work

Breakpoint locations in term of XPath expressions

Monitoring temporal contracts

Replay debugging

47
plt­scheme.org
In Summary

First-class event streams in FrTime can define reusable debugging tools

48
plt­scheme.org
In Summary

First-class event streams in FrTime can define reusable debugging tools

Ad-hoc languages are hard to get right – reuse existing platforms

49
plt­scheme.org
In Summary

First-class event streams in FrTime can define reusable debugging tools

Ad-hoc languages are hard to get right – reuse existing platforms

There is an interesting language design question in scriptable debuggers


– independently of performance

50
plt­scheme.org
Software

MzTake: the scriptable debugger (In Scheme, for Scheme)

http://www.cs.brown.edu/research/plt/software/mztake/

51
plt­scheme.org

You might also like