blob: 9c52f2a09f3050b9dd2be7befaa3681fdd7ea188 [file] [log] [blame]
Shinichiro Hamajib69bf8a2015-06-10 14:52:06 +09001// Copyright 2015 Google Inc. All rights reserved
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +090015package main
16
17import (
18 "fmt"
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090019 "io"
20 "os"
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +090021 "sort"
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +090022 "sync"
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +090023 "time"
24)
25
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090026type traceEventT struct {
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +090027 mu sync.Mutex
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090028 f io.WriteCloser
29 t0 time.Time
30 pid int
31}
32
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +090033const (
34 traceEventMain = iota + 1
35 traceEventFindCache
Fumitoshi Ukai83410132015-06-15 14:50:07 +090036 traceEventFindCacheLeaves
37 traceEventFindCacheFiles
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +090038)
39
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090040var traceEvent traceEventT
41
42func (t *traceEventT) start(f io.WriteCloser) {
43 t.f = f
44 t.t0 = time.Now()
45 fmt.Fprint(t.f, "[ ")
46}
47
48func (t *traceEventT) enabled() bool {
49 return t.f != nil
50}
51
52func (t *traceEventT) stop() {
53 fmt.Fprint(t.f, "\n]\n")
54 t.f.Close()
55}
56
57type event struct {
58 name, v string
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +090059 tid int
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090060 t time.Time
Fumitoshi Ukaicb393c52015-06-11 15:34:10 +090061 emit bool
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090062}
63
Fumitoshi Ukai83410132015-06-15 14:50:07 +090064func (t *traceEventT) begin(name string, v Value, tid int) event {
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090065 var e event
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +090066 e.tid = tid
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090067 e.t = time.Now()
Fumitoshi Ukai6ab72dd2015-06-11 15:45:52 +090068 if t.f != nil || katiEvalStatsFlag {
69 e.name = name
Fumitoshi Ukai83410132015-06-15 14:50:07 +090070 e.v = v.String()
Fumitoshi Ukai6ab72dd2015-06-11 15:45:52 +090071 }
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090072 if t.f != nil {
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +090073 e.emit = name == "include" || name == "shell" || name == "findcache"
Fumitoshi Ukaicb393c52015-06-11 15:34:10 +090074 if e.emit {
Fumitoshi Ukai83410132015-06-15 14:50:07 +090075 t.emit("B", e, e.t.Sub(t.t0))
Fumitoshi Ukai432a2422015-06-11 15:16:29 +090076 }
77 }
78 return e
79}
80
Fumitoshi Ukai83410132015-06-15 14:50:07 +090081func (t *traceEventT) emit(ph string, e event, ts time.Duration) {
Fumitoshi Ukaif543f4d2015-06-15 15:21:47 +090082 t.mu.Lock()
83 defer t.mu.Unlock()
Fumitoshi Ukai83410132015-06-15 14:50:07 +090084
85 if t.pid == 0 {
86 t.pid = os.Getpid()
87 } else {
88 fmt.Fprintf(t.f, ",\n")
89 }
90 fmt.Fprintf(t.f, `{"pid":%d,"tid":%d,"ts":%d,"ph":%q,"cat":%q,"name":%q,"args":{}}`,
91 t.pid,
92 e.tid,
93 ts.Nanoseconds()/1e3,
94 ph,
95 e.name,
96 e.v,
97 )
98}
99
100func (t *traceEventT) end(e event) {
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900101 if t.f != nil {
Fumitoshi Ukaicb393c52015-06-11 15:34:10 +0900102 if e.emit {
Fumitoshi Ukai83410132015-06-15 14:50:07 +0900103 t.emit("E", e, time.Since(t.t0))
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900104 }
105 }
106 addStats(e.name, e.v, e.t)
107}
108
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900109type statsData struct {
110 Name string
111 Count int
112 Longest time.Duration
113 Total time.Duration
114}
115
116var stats = map[string]statsData{}
117
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900118func addStats(name, v string, t time.Time) {
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +0900119 if !katiEvalStatsFlag {
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900120 return
121 }
Fumitoshi Ukai358c68a2015-06-08 13:12:55 +0900122 d := time.Since(t)
Fumitoshi Ukai432a2422015-06-11 15:16:29 +0900123 key := fmt.Sprintf("%s:%s", name, v)
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900124 s := stats[key]
125 if d > s.Longest {
126 s.Longest = d
127 }
128 s.Total += d
129 s.Count++
130 stats[key] = s
131}
132
133func dumpStats() {
Fumitoshi Ukai586b02a2015-05-08 00:23:10 +0900134 if !katiEvalStatsFlag {
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900135 return
136 }
137 var sv byTotalTime
138 for k, v := range stats {
139 v.Name = k
140 sv = append(sv, v)
141 }
142 sort.Sort(sv)
Fumitoshi Ukai47f401f2015-04-30 17:29:50 +0900143 fmt.Println("count,longest(ns),total(ns),longest,total,name")
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900144 for _, s := range sv {
Fumitoshi Ukai47f401f2015-04-30 17:29:50 +0900145 fmt.Printf("%d,%d,%d,%v,%v,%s\n", s.Count, s.Longest, s.Total, s.Longest, s.Total, s.Name)
Fumitoshi Ukai6ac7f692015-04-15 17:13:51 +0900146 }
147}
148
149type byTotalTime []statsData
150
151func (b byTotalTime) Len() int { return len(b) }
152func (b byTotalTime) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
153func (b byTotalTime) Less(i, j int) bool {
154 return b[i].Total > b[j].Total
155}