<commit_before>package tachymeter

import (
	"fmt"
	"sync"
	"time"
)

type Config struct {
	Size int
	Safe bool // Optionally lock if concurrent access is needed.
}

type timeSlice []time.Duration

type Tachymeter struct {
	sync.Mutex
	Safe          bool
	Times         timeSlice
	TimesPosition int
	TimesUsed     int
	Count         int
}

type Metrics struct {
	Time struct {
		Total    time.Duration
		Avg      time.Duration
		Median   time.Duration
		p95      time.Duration
		Long5p  time.Duration
		Short5p time.Duration
		Max      time.Duration
		Min      time.Duration
	}
	Rate struct {
		Second float64
	}
	Samples int
	Count   int
}

func New(c *Config) *Tachymeter {
	return &Tachymeter{
		Times: make([]time.Duration, c.Size),
		Safe:  c.Safe,
	}
}

// AddTime adds a time.Duration to the Tachymeter.Times
// slice, then increments the position.
func (m *Tachymeter) AddTime(t time.Duration) {
	if m.Safe {
		m.Lock()
		defer m.Unlock()
	}

	// If we're at the end, rollover and
	// start overwriting.
	if m.TimesPosition == len(m.Times) {
		m.TimesPosition = 0
	}

	m.Times[m.TimesPosition] = t
	m.TimesPosition++
	if m.TimesUsed < len(m.Times) {
		m.TimesUsed++
	}
}

// AddCount simply counts events.
func (m *Tachymeter) AddCount(i int) {
	if m.Safe {
		m.Lock()
		defer m.Unlock()
	}

	m.Count += i
}

// Dump prints out a generic output of
// all gathered metrics.
func (m *Tachymeter) Dump() {
	metrics := m.Calc()
	fmt.Printf("%d samples of %d events\n", metrics.Samples, metrics.Count)
	fmt.Printf("Total:\t\t%s\n", metrics.Time.Total)
	fmt.Printf("Avg.:\t\t%s\n", metrics.Time.Avg)
	fmt.Printf("95%%ile:\t\t%s\n", metrics.Time.p95)
	fmt.Printf("Longest 5%%:\t%s\n", metrics.Time.Long10p)
	fmt.Printf("Shortest 5%%:\t%s\n", metrics.Time.Short10p)
	fmt.Printf("Max:\t\t%s\n", metrics.Time.Max)
	fmt.Printf("Min:\t\t%s\n", metrics.Time.Min)
	fmt.Printf("Rate/sec.:\t%.2f\n", metrics.Rate.Second)
}<commit_msg>fixed var ref<commit_after>package tachymeter

import (
	"fmt"
	"sync"
	"time"
)

type Config struct {
	Size int
	Safe bool // Optionally lock if concurrent access is needed.
}

type timeSlice []time.Duration

type Tachymeter struct {
	sync.Mutex
	Safe          bool
	Times         timeSlice
	TimesPosition int
	TimesUsed     int
	Count         int
}

type Metrics struct {
	Time struct {
		Total    time.Duration
		Avg      time.Duration
		Median   time.Duration
		p95      time.Duration
		Long5p  time.Duration
		Short5p time.Duration
		Max      time.Duration
		Min      time.Duration
	}
	Rate struct {
		Second float64
	}
	Samples int
	Count   int
}

func New(c *Config) *Tachymeter {
	return &Tachymeter{
		Times: make([]time.Duration, c.Size),
		Safe:  c.Safe,
	}
}

// AddTime adds a time.Duration to the Tachymeter.Times
// slice, then increments the position.
func (m *Tachymeter) AddTime(t time.Duration) {
	if m.Safe {
		m.Lock()
		defer m.Unlock()
	}

	// If we're at the end, rollover and
	// start overwriting.
	if m.TimesPosition == len(m.Times) {
		m.TimesPosition = 0
	}

	m.Times[m.TimesPosition] = t
	m.TimesPosition++
	if m.TimesUsed < len(m.Times) {
		m.TimesUsed++
	}
}

// AddCount simply counts events.
func (m *Tachymeter) AddCount(i int) {
	if m.Safe {
		m.Lock()
		defer m.Unlock()
	}

	m.Count += i
}

// Dump prints out a generic output of
// all gathered metrics.
func (m *Tachymeter) Dump() {
	metrics := m.Calc()
	fmt.Printf("%d samples of %d events\n", metrics.Samples, metrics.Count)
	fmt.Printf("Total:\t\t%s\n", metrics.Time.Total)
	fmt.Printf("Avg.:\t\t%s\n", metrics.Time.Avg)
	fmt.Printf("95%%ile:\t\t%s\n", metrics.Time.p95)
	fmt.Printf("Longest 5%%:\t%s\n", metrics.Time.Long5p)
	fmt.Printf("Shortest 5%%:\t%s\n", metrics.Time.Short5p)
	fmt.Printf("Max:\t\t%s\n", metrics.Time.Max)
	fmt.Printf("Min:\t\t%s\n", metrics.Time.Min)
	fmt.Printf("Rate/sec.:\t%.2f\n", metrics.Rate.Second)
}
{'fraction_non_alphanumeric': 0.14493506493506494, 'fraction_numerical': 0.008831168831168832, 'mean_word_length': 3.0665258711721224, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1279373', 'n_tokens_mistral': 1549, 'n_tokens_neox': 1501, 'n_words': 356}