summaryrefslogtreecommitdiff
path: root/js/src/tracevis/binlog.py
blob: 84681c2185db5e4274c3e2e8bb94b96c0c5b0979 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# Parse the binary log file of activity timings.
#
# If run as a script, print a summary of the log, giving the total
# time in each activity.

import sys
import struct

from config import *
from acts import *

S_INTERP = 1
assert states[S_INTERP] == 'interpret'

REASON_COUNT = len(reasons)

def tuple_to_reason_index(rec):
    if rec[1]:
        return rec[1]
    return REASON_COUNT + rec[0]

def reason_index_label(i):
    if i == REASON_COUNT:
        return 'start'
    if i > REASON_COUNT:
        return states[i - REASON_COUNT]
    return reasons[i]

class History(object):
    def __init__(self):
        # list of (state, reason, time from start) tuples
        self.transitions = []
        # list of total time
        self.state_summary = [ 0 ] * len(states)
        # list of (count, total time) tuples
        self.reason_summary = [ [0, 0] for _ in range(len(reasons) + len(states)) ]

        self.t0 = None
        self.stack = []
        self.to_interp = None

    def write(self, state, reason, time):
        self.transitions.append((state, reason, time - self.t0))

    def transition(self, rec0, rec1):
        t1 = rec1[2]
        dt = rec1[2] - rec0[2]
        self.state_summary[rec0[0]] += dt

        self.write(rec0[0], 0, rec1[2])
        
        # Transition to interpreter
        if rec0[0] != S_INTERP and rec1[0] == S_INTERP:
            self.to_interp = (rec0[0], rec1[1], rec1[2])
        
        # Transition from interpreter
        if rec0[0] == S_INTERP and rec1[0] != S_INTERP:
            rs_tup = self.reason_summary[tuple_to_reason_index(self.to_interp)]
            rs_tup[0] += 1
            rs_tup[1] += dt

    def enter(self, rec):
        if rec[0] >= event_start:
            self.write(*rec)
        else:
            if self.t0 is None:
                self.t0 = rec[2]
                self.stack.append([0, 0, rec[2]])
            self.transition(self.stack[-1], rec)
            self.stack.append(rec)

    def exit(self, rec):
        entry = self.stack.pop()
        prior = self.stack[-1]
        exit = rec
        exit[0] = prior[0]
        self.transition(entry, exit)
        prior[1] = rec[1]
        prior[2] = rec[2]

def read_history(filename):
    h = History()
    f = open(filename)
    while True:
        raw = f.read(8)
        if not raw:
            break
        ull = struct.unpack_from('Q', raw, 0)[0]
        rec = [(ull >> 60) & 0xf,
               (ull >> 55) & 0x1f,
               ull & ~(0x1ff << 55)]
        if rec[0]:
            h.enter(rec)
        else:
            h.exit(rec)
    return h

def summary(hist):
    ep = 0       # estimated progress

    print 'Activity duration summary:'
    print
    cycles = hist.state_summary
    for sn, cyc, xf in zip(states, cycles, speedups):
        if sn == 'exitlast': continue
        ep += xf * cyc
        print '%-12s %12.6f'%(sn, cyc/CPU_SPEED * 1000)
    print '-'*25
    print '%-12s %12.6f'%('Subtotal', sum(cycles[1:])/CPU_SPEED * 1000)
    print '%-12s %12.6f'%('Non-JS', cycles[0]/CPU_SPEED * 1000)
    print '='*25
    print '%-12s %12.6f'%('Total', sum(cycles)/CPU_SPEED * 1000)

    print 'Estimated speedup:  %.2fx'%(ep/sum(cycles[1:]))

    print
    print 'Reasons for transitions to interpret:'
    print '%-12s %12s %8s %12s'%(
        'Reason', 'sum (ms)', 'N', 'mean (us)')
    rl = [ (rc[1], rc[0], reason_index_label(i))
            for i, rc in enumerate(hist.reason_summary) ]
    rl.sort(reverse=1)
    for cyc, n, label in rl:
        if cyc == 0: continue
        print '%-12s %12.3f %8d %12.3f'%(
            label, 
            cyc/CPU_SPEED*1000, 
            n, 
            cyc/CPU_SPEED*1000000/n,
            )

if __name__ == '__main__':
    if len(sys.argv) <= 1:
        print >> sys.stderr, "usage: python binlog.py infile"
        sys.exit(1);

    filename = sys.argv[1]
    history = read_history(filename)

    summary(history)