Commit b251d7fb authored by Austin Clements's avatar Austin Clements

cmd/trace: display p99.9, p99 and p95 MUT

This uses the mutator utilization distribution to compute the p99.9,
p99, and p95 mutator utilization topograph lines and display them
along with the MMU.

Change-Id: I8c7e0ec326aa4bc00619ec7562854253f01cc802
Reviewed-on: https://go-review.googlesource.com/c/60800
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarHyang-Ah Hana Kim <hyangah@gmail.com>
parent 33563d1c
...@@ -88,6 +88,14 @@ func httpMMUPlot(w http.ResponseWriter, r *http.Request) { ...@@ -88,6 +88,14 @@ func httpMMUPlot(w http.ResponseWriter, r *http.Request) {
return return
} }
var quantiles []float64
for _, flagStr := range strings.Split(r.FormValue("flags"), "|") {
if flagStr == "mut" {
quantiles = []float64{0, 1 - .999, 1 - .99, 1 - .95}
break
}
}
// Find a nice starting point for the plot. // Find a nice starting point for the plot.
xMin := time.Second xMin := time.Second
for xMin > 1 { for xMin > 1 {
...@@ -114,15 +122,21 @@ func httpMMUPlot(w http.ResponseWriter, r *http.Request) { ...@@ -114,15 +122,21 @@ func httpMMUPlot(w http.ResponseWriter, r *http.Request) {
// Compute MMU curve. // Compute MMU curve.
logMin, logMax := math.Log(float64(xMin)), math.Log(float64(xMax)) logMin, logMax := math.Log(float64(xMin)), math.Log(float64(xMax))
const samples = 100 const samples = 100
plot := make([][2]float64, samples) plot := make([][]float64, samples)
for i := 0; i < samples; i++ { for i := 0; i < samples; i++ {
window := time.Duration(math.Exp(float64(i)/(samples-1)*(logMax-logMin) + logMin)) window := time.Duration(math.Exp(float64(i)/(samples-1)*(logMax-logMin) + logMin))
y := mmuCurve.MMU(window) if quantiles == nil {
plot[i] = [2]float64{float64(window), y} plot[i] = make([]float64, 2)
plot[i][1] = mmuCurve.MMU(window)
} else {
plot[i] = make([]float64, 1+len(quantiles))
copy(plot[i][1:], mmuCurve.MUD(window, quantiles))
}
plot[i][0] = float64(window)
} }
// Create JSON response. // Create JSON response.
err = json.NewEncoder(w).Encode(map[string]interface{}{"xMin": int64(xMin), "xMax": int64(xMax), "curve": plot}) err = json.NewEncoder(w).Encode(map[string]interface{}{"xMin": int64(xMin), "xMax": int64(xMax), "quantiles": quantiles, "curve": plot})
if err != nil { if err != nil {
log.Printf("failed to serialize response: %v", err) log.Printf("failed to serialize response: %v", err)
return return
...@@ -150,6 +164,10 @@ var templMMU = `<!doctype html> ...@@ -150,6 +164,10 @@ var templMMU = `<!doctype html>
else { return ns / 1e9 + 's'; } else { return ns / 1e9 + 's'; }
} }
function niceQuantile(q) {
return 'p' + q*100;
}
function mmuFlags() { function mmuFlags() {
var flags = ""; var flags = "";
$("#options input").each(function(i, elt) { $("#options input").each(function(i, elt) {
...@@ -181,6 +199,11 @@ var templMMU = `<!doctype html> ...@@ -181,6 +199,11 @@ var templMMU = `<!doctype html>
var data = new google.visualization.DataTable(); var data = new google.visualization.DataTable();
data.addColumn('number', 'Window duration'); data.addColumn('number', 'Window duration');
data.addColumn('number', 'Minimum mutator utilization'); data.addColumn('number', 'Minimum mutator utilization');
if (plotData.quantiles) {
for (var i = 1; i < plotData.quantiles.length; i++) {
data.addColumn('number', niceQuantile(1 - plotData.quantiles[i]) + ' MU');
}
}
data.addRows(curve); data.addRows(curve);
for (var i = 0; i < curve.length; i++) { for (var i = 0; i < curve.length; i++) {
data.setFormattedValue(i, 0, niceDuration(curve[i][0])); data.setFormattedValue(i, 0, niceDuration(curve[i][0]));
...@@ -201,6 +224,7 @@ var templMMU = `<!doctype html> ...@@ -201,6 +224,7 @@ var templMMU = `<!doctype html>
maxValue: 1.0, maxValue: 1.0,
}, },
legend: { position: 'none' }, legend: { position: 'none' },
focusTarget: 'category',
width: 900, width: 900,
height: 500, height: 500,
chartArea: { width: '80%', height: '80%' }, chartArea: { width: '80%', height: '80%' },
...@@ -208,6 +232,10 @@ var templMMU = `<!doctype html> ...@@ -208,6 +232,10 @@ var templMMU = `<!doctype html>
for (var v = plotData.xMin; v <= plotData.xMax; v *= 10) { for (var v = plotData.xMin; v <= plotData.xMax; v *= 10) {
options.hAxis.ticks.push({v:v, f:niceDuration(v)}); options.hAxis.ticks.push({v:v, f:niceDuration(v)});
} }
if (plotData.quantiles) {
options.vAxis.title = 'Mutator utilization';
options.legend.position = 'in';
}
var container = $('#mmu_chart'); var container = $('#mmu_chart');
container.empty(); container.empty();
...@@ -298,6 +326,11 @@ var templMMU = `<!doctype html> ...@@ -298,6 +326,11 @@ var templMMU = `<!doctype html>
<input type="checkbox" id="sweep"><label for="sweep">Sweep</label> <input type="checkbox" id="sweep"><label for="sweep">Sweep</label>
<span class="help">?<span>Sweep reclaims unused memory between GCs. (Enabling this may be very slow.).</span></span><br/> <span class="help">?<span>Sweep reclaims unused memory between GCs. (Enabling this may be very slow.).</span></span><br/>
</p> </p>
<p>
<b>Display</b><br/>
<input type="checkbox" id="mut"><label for="mut">Show percentiles</label>
<span class="help">?<span>Display percentile mutator utilization in addition to minimum. E.g., p99 MU drops the worst 1% of windows.</span></span><br/>
</p>
</div> </div>
</div> </div>
<div id="details">Select a point for details.</div> <div id="details">Select a point for details.</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment