// parseHostTag parses and strips the host tag from the provided event. func parseHostTag(event *statse.Event) (string, error) { var tagsArray [128]byte tags := append(tagsArray[:0], event.Tags...) i := bytes.Index(tags, []byte("host=")) if i == -1 || (i > 0 && tags[i-1] != ' ') { return "", errors.New("missing host tag") } tag := tags[i:] if i := bytes.IndexByte(tag, ' '); i > 0 { tag = tag[:i] } host := string(tag[bytes.IndexByte(tag, '=')+1:]) if host == "" { return "", errors.New("host tag has empty value") } tagLen := len("host=") + len(host) if i == 0 { // host is the first tag. copy(tags[i:], tags[i+tagLen:]) tags = tags[:len(tags)-tagLen] } else { // host is not the first tag, strip the leading space too. copy(tags[i-1:], tags[i+tagLen:]) tags = tags[:len(tags)-tagLen-1] } event.Tags = string(tags) return host, nil }
func BenchmarkServer(b *testing.B) { const ( nmetrics = 1000 npermutations = 50 nhosts = 20 nstatistics = 10000 ) var ( event = statse.Event{} metric []string statistics [][]statse.Statistic ) for metricID := 0; metricID < nmetrics; metricID++ { metric = append(metric, fmt.Sprintf("metric%d", metricID)) } for statisticID := 0; statisticID < nstatistics; statisticID++ { statistics = append(statistics, []statse.Statistic{ {Key: statse.Time, Value: float32(rand.NormFloat64()*10 + 12.1)}, {Key: statse.TTFB, Value: float32(rand.NormFloat64()*10 + 10.1)}, {Key: statse.Size, Value: float32(rand.NormFloat64()*5000 + 12345)}, }) } client := make([]testServerConn, 10) NextClient: for i := 0; i < len(client); i++ { enc := gob.NewEncoder(&client[i].buf) metricID := 0 statisticsID := 0 for i := 0; ; { event.Metric = metric[metricID] metricID = (metricID + 1) % len(metric) for j := 0; j < npermutations; j++ { event.Tags = fmt.Sprintf("tags_permutation=%d", j) event.Statistics = statistics[statisticsID] statisticsID = (statisticsID + 1) % len(statistics) enc.Encode(&event) if i++; i >= b.N/len(client) { continue NextClient } } } } b.ResetTimer() b.ReportAllocs() var totalBytes int64 for _, conn := range client { totalBytes += int64(conn.buf.Len()) } b.SetBytes(totalBytes / int64(b.N)) // Skip the benchmark because the initialisation above is too heavy for use with // the -cpuprofile flag. // https://code.google.com/p/go/issues/detail?id=8213 b.Skip() binDst, _ := os.Create("/tmp/cpu.test") binSrc, _ := os.Open(os.Args[0]) io.Copy(binDst, binSrc) cpuOut, _ := os.Create("/tmp/cpu.out") pprof.StartCPUProfile(cpuOut) defer pprof.StopCPUProfile() store := newStore() done := make(chan bool) for _, conn := range client { conn := conn serverConn := &serverConn{&conn, store} go func() { serverConn.loop() done <- true }() } for i := 0; i < len(client); i++ { <-done } job := snapshotJob{ Time: time.Unix(0, 0), Store: store, } job.do() }