func profile(clk clock.Clock, w io.Writer, r io.Reader) (io.Writer, io.Reader, func() TimeProfile) { preciseWriter := &preciseTimedWriter{clk: clk, w: w} preciseReader := &preciseTimedReader{clk: clk, r: r} start := clk.Now() return preciseWriter, preciseReader, func() TimeProfile { return TimeProfile{ Total: clk.Now().Sub(start), WaitRead: preciseReader.WaitRead(), WaitWrite: preciseWriter.WaitWrite(), } } }
func profileSample(clk clock.Clock, w io.Writer, r io.Reader, res time.Duration) (io.Writer, io.Reader, func() SamplingProfile) { samplingWriter := &samplingTimeWriter{w: w} samplingReader := &samplingTimeReader{r: r} start := clk.Now() done := make(chan struct{}) samples := SamplingProfile{} go func() { ticker := clk.Ticker(res) defer ticker.Stop() for { select { case <-ticker.C: isWriting := atomic.LoadUint32(&samplingWriter.state) == stateBlocked isReading := atomic.LoadUint32(&samplingReader.state) == stateBlocked if isWriting { samples.Writing++ } else { samples.NotWriting++ } if isReading { samples.Reading++ } else { samples.NotReading++ } case <-done: return } } }() return samplingWriter, samplingReader, func() SamplingProfile { close(done) total := clk.Now().Sub(start) samples.TimeProfile = TimeProfile{ Total: total, WaitRead: time.Duration(float64(samples.Reading) / float64(samples.Reading+samples.NotReading) * float64(total)), WaitWrite: time.Duration(float64(samples.Writing) / float64(samples.Writing+samples.NotWriting) * float64(total)), } return samples } }