Skip to content

Instantly share code, notes, and snippets.

@odeke-em
Created December 15, 2019 09:40
Show Gist options
  • Save odeke-em/6e499d7b0c8103be36f10b0d2c41aacb to your computer and use it in GitHub Desktop.
Save odeke-em/6e499d7b0c8103be36f10b0d2c41aacb to your computer and use it in GitHub Desktop.
package main
import (
"io/ioutil"
"math"
"os"
"os/exec"
"path/filepath"
"testing"
"time"
)
const prog = `
package main
import (
"fmt"
"html"
"log"
"net/http"
)
func main() {
http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
})
go http.ListenAndServe(":8080", nil)
// Exit immediately so we can easily measure startup.
log.Printf("Exiting...")
}`
func TestSlowStart(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "issue36028")
if err != nil {
t.Fatalf("Failed to create tmp directory: %v", err)
}
defer os.RemoveAll(tmpDir)
mainGoFile := filepath.Join(tmpDir, "http.go")
if err := ioutil.WriteFile(mainGoFile, []byte(prog), 0600); err != nil {
t.Fatalf("Failed to write file: %v", err)
}
staticFile := filepath.Join(tmpDir, "http.static")
pieFile := filepath.Join(tmpDir, "http.ext.pie")
pieLinkFile := filepath.Join(tmpDir, "http.int.pie")
var noEnv []string
_, output, err := execIt(noEnv, "go", "build", "-o", staticFile, mainGoFile)
if err != nil {
t.Fatalf("Failed to build object file: %v\n%s", err, output)
}
_, output, err = execIt(noEnv, "go", "build", "-buildmode=pie", "-o", pieFile, mainGoFile)
if err != nil {
t.Fatalf("Failed to build PIE file: %v\n%s", err, output)
}
cgoEnabled0 := append(os.Environ(), "CGO_ENABLED=0")
_, output, err = execIt(cgoEnabled0, "go", "build", "-ldflags=-linkmode=internal", "-o", pieLinkFile, mainGoFile)
if err != nil {
t.Fatalf("Failed to build PIE -linkmode file: %v\n%s", err, output)
}
durStatic, _, _ := execIt(noEnv, staticFile)
durPIE, _, _ := execIt(noEnv, pieFile)
durPIELink, _, _ := execIt(noEnv, pieLinkFile)
t.Logf("\ndurObj: %s\ndurPIE: %s\ndurPIELink: %s", durStatic, durPIE, durPIELink)
values := []struct {
name string
value time.Duration
}{
{"durStatic", durStatic},
{"durPIE", durPIE},
{"durPIELink", durPIELink},
}
sum := 0.0
for _, value := range values {
sum += float64(value.value)
}
mean := sum / float64(len(values))
sumOfSquares := 0.0
for _, value := range values {
sumOfSquares += math.Pow(float64(value.value)-mean, 2.0)
}
variance := sumOfSquares / float64(len(values))
stdDev := math.Pow(variance, 0.5)
t.Logf("stdDev: %s", time.Duration(stdDev))
// Our heuristic here is that anomalies are those whose |value - stdDev| >= 3 * stdDev
anomalyCutoff := 3 * stdDev + mean
for _, value := range values {
if diff := math.Abs(float64(value.value) - stdDev); diff > anomalyCutoff {
t.Errorf("Anomaly: %q: %s |diff| %s > 3Sigma: %s", value.name, value.value, time.Duration(diff), time.Duration(anomalyCutoff))
}
}
}
func execIt(env []string, prog string, args ...string) (dur time.Duration, output []byte, err error) {
startTime := time.Now()
defer func() {
dur = time.Now().Sub(startTime)
}()
cmd := exec.Command(prog, args...)
cmd.Env = env
output, err = cmd.CombinedOutput()
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment