1
- // Copyright 2017 The Go Authors. All rights reserved.
1
+ // Copyright 2023 The Go Authors. All rights reserved.
2
2
// Use of this source code is governed by a BSD-style
3
3
// license that can be found in the LICENSE file.
4
4
23
23
// could potentially put confidence intervals on these estimates and
24
24
// render this progressively as we refine the distributions.
25
25
26
- package main
26
+ package traceviewer
27
27
28
28
import (
29
29
"encoding/json"
30
30
"fmt"
31
31
"internal/trace"
32
- "internal/trace/traceviewer"
33
32
"log"
34
33
"math"
35
34
"net/http"
@@ -39,10 +38,21 @@ import (
39
38
"time"
40
39
)
41
40
42
- func init () {
43
- http .HandleFunc ("/mmu" , httpMMU )
44
- http .HandleFunc ("/mmuPlot" , httpMMUPlot )
45
- http .HandleFunc ("/mmuDetails" , httpMMUDetails )
41
+ type MutatorUtilFunc func (trace.UtilFlags ) ([][]trace.MutatorUtil , error )
42
+
43
+ func InstallMMUHandlers (mux * http.ServeMux , ranges []Range , f MutatorUtilFunc ) {
44
+ mmu := & mmu {
45
+ cache : make (map [trace.UtilFlags ]* mmuCacheEntry ),
46
+ f : f ,
47
+ ranges : ranges ,
48
+ }
49
+ mux .HandleFunc ("/mmu" , func (w http.ResponseWriter , r * http.Request ) {
50
+ // N.B. templMMU has Javascript that implicitly relies upon the existence
51
+ // of /mmuPlot and /mmuDetails on the same server.
52
+ http .ServeContent (w , r , "" , time.Time {}, strings .NewReader (templMMU ))
53
+ })
54
+ mux .HandleFunc ("/mmuPlot" , mmu .HandlePlot )
55
+ mux .HandleFunc ("/mmuDetails" , mmu .HandleDetails )
46
56
}
47
57
48
58
var utilFlagNames = map [string ]trace.UtilFlags {
@@ -53,58 +63,54 @@ var utilFlagNames = map[string]trace.UtilFlags{
53
63
"sweep" : trace .UtilSweep ,
54
64
}
55
65
66
+ func requestUtilFlags (r * http.Request ) trace.UtilFlags {
67
+ var flags trace.UtilFlags
68
+ for _ , flagStr := range strings .Split (r .FormValue ("flags" ), "|" ) {
69
+ flags |= utilFlagNames [flagStr ]
70
+ }
71
+ return flags
72
+ }
73
+
56
74
type mmuCacheEntry struct {
57
75
init sync.Once
58
76
util [][]trace.MutatorUtil
59
77
mmuCurve * trace.MMUCurve
60
78
err error
61
79
}
62
80
63
- var mmuCache struct {
64
- m map [trace.UtilFlags ]* mmuCacheEntry
65
- lock sync.Mutex
81
+ type mmu struct {
82
+ mu sync.Mutex
83
+ cache map [trace.UtilFlags ]* mmuCacheEntry
84
+ f MutatorUtilFunc
85
+ ranges []Range
66
86
}
67
87
68
- func init () {
69
- mmuCache .m = make (map [trace.UtilFlags ]* mmuCacheEntry )
70
- }
71
-
72
- func getMMUCurve (r * http.Request ) ([][]trace.MutatorUtil , * trace.MMUCurve , error ) {
73
- var flags trace.UtilFlags
74
- for _ , flagStr := range strings .Split (r .FormValue ("flags" ), "|" ) {
75
- flags |= utilFlagNames [flagStr ]
88
+ func (m * mmu ) get (flags trace.UtilFlags ) ([][]trace.MutatorUtil , * trace.MMUCurve , error ) {
89
+ m .mu .Lock ()
90
+ entry := m .cache [flags ]
91
+ if entry == nil {
92
+ entry = new (mmuCacheEntry )
93
+ m .cache [flags ] = entry
76
94
}
95
+ m .mu .Unlock ()
77
96
78
- mmuCache .lock .Lock ()
79
- c := mmuCache .m [flags ]
80
- if c == nil {
81
- c = new (mmuCacheEntry )
82
- mmuCache .m [flags ] = c
83
- }
84
- mmuCache .lock .Unlock ()
85
-
86
- c .init .Do (func () {
87
- events , err := parseEvents ()
97
+ entry .init .Do (func () {
98
+ util , err := m .f (flags )
88
99
if err != nil {
89
- c .err = err
100
+ entry .err = err
90
101
} else {
91
- c .util = trace . MutatorUtilization ( events , flags )
92
- c .mmuCurve = trace .NewMMUCurve (c . util )
102
+ entry .util = util
103
+ entry .mmuCurve = trace .NewMMUCurve (util )
93
104
}
94
105
})
95
- return c .util , c .mmuCurve , c .err
96
- }
97
-
98
- // httpMMU serves the MMU plot page.
99
- func httpMMU (w http.ResponseWriter , r * http.Request ) {
100
- http .ServeContent (w , r , "" , time.Time {}, strings .NewReader (templMMU ))
106
+ return entry .util , entry .mmuCurve , entry .err
101
107
}
102
108
103
- // httpMMUPlot serves the JSON data for the MMU plot.
104
- func httpMMUPlot (w http.ResponseWriter , r * http.Request ) {
105
- mu , mmuCurve , err := getMMUCurve ( r )
109
+ // HandlePlot serves the JSON data for the MMU plot.
110
+ func ( m * mmu ) HandlePlot (w http.ResponseWriter , r * http.Request ) {
111
+ mu , mmuCurve , err := m . get ( requestUtilFlags ( r ) )
106
112
if err != nil {
107
- http .Error (w , fmt .Sprintf ("failed to parse events : %v" , err ), http .StatusInternalServerError )
113
+ http .Error (w , fmt .Sprintf ("failed to produce MMU data : %v" , err ), http .StatusInternalServerError )
108
114
return
109
115
}
110
116
@@ -358,11 +364,11 @@ var templMMU = `<!doctype html>
358
364
</html>
359
365
`
360
366
361
- // httpMMUDetails serves details of an MMU graph at a particular window.
362
- func httpMMUDetails (w http.ResponseWriter , r * http.Request ) {
363
- _ , mmuCurve , err := getMMUCurve ( r )
367
+ // HandleDetails serves details of an MMU graph at a particular window.
368
+ func ( m * mmu ) HandleDetails (w http.ResponseWriter , r * http.Request ) {
369
+ _ , mmuCurve , err := m . get ( requestUtilFlags ( r ) )
364
370
if err != nil {
365
- http .Error (w , fmt .Sprintf ("failed to parse events : %v" , err ), http .StatusInternalServerError )
371
+ http .Error (w , fmt .Sprintf ("failed to produce MMU data : %v" , err ), http .StatusInternalServerError )
366
372
return
367
373
}
368
374
@@ -377,7 +383,7 @@ func httpMMUDetails(w http.ResponseWriter, r *http.Request) {
377
383
// Construct a link for each window.
378
384
var links []linkedUtilWindow
379
385
for _ , ui := range worst {
380
- links = append (links , newLinkedUtilWindow (ui , time .Duration (window )))
386
+ links = append (links , m . newLinkedUtilWindow (ui , time .Duration (window )))
381
387
}
382
388
383
389
err = json .NewEncoder (w ).Encode (links )
@@ -392,10 +398,10 @@ type linkedUtilWindow struct {
392
398
URL string
393
399
}
394
400
395
- func newLinkedUtilWindow (ui trace.UtilWindow , window time.Duration ) linkedUtilWindow {
401
+ func ( m * mmu ) newLinkedUtilWindow (ui trace.UtilWindow , window time.Duration ) linkedUtilWindow {
396
402
// Find the range containing this window.
397
- var r traceviewer. Range
398
- for _ , r = range ranges {
403
+ var r Range
404
+ for _ , r = range m . ranges {
399
405
if r .EndTime > ui .Time {
400
406
break
401
407
}
0 commit comments