Pkg.go.dev is a new destination for Go discovery & docs. Check it out at pkg.go.dev/github.com/aybabtme/iocontrol and share your feedback.

package iocontrol

import "github.com/aybabtme/iocontrol"

Package iocontrol offers `io.Writer` and `io.Reader` implementations that allow one to measure and throttle the rate at which data is transferred.

counter.go doc.go limiter.go measure.go pool.go stream_profile.go throttle.go

❖ const ( KiB = 1 << 10 MiB = 1 << 20 GiB = 1 << 30 )

Orders of magnitude of data, in kibibyte (powers of 2, or multiples of 1024). See https://en.wikipedia.org/wiki/Kibibyte.

❖ func Profile(w io.Writer, r io.Reader) (pw io.Writer, pr io.Reader, done func() TimeProfile)

Profile will wrap a writer and reader pair and profile where time is spent: writing or reading. The result is returned when the `done` func is called. The `done` func can be called multiple times.

There is a small performance overhead of ~µs per Read/Write call. This is negligible in most I/O workloads. If the overhead is too much for your needs, use the `ProfileSample` call.

❖ func ProfileSample(w io.Writer, r io.Reader, res time.Duration) (pw io.Writer, pr io.Reader, done func() SamplingProfile)

ProfileSample will wrap a writer and reader pair and collect samples of where time is spent: writing or reading. The result is an approximation that is returned when the `done` func is called. The `done` func can be called *only once*.

This call is not as precise as the `Profile` call, but the performance overhead is much reduced.

❖ type MeasuredReader struct { // contains filtered or unexported fields }

MeasuredReader wraps a reader and tracks how many bytes are read to it.

NewMeasuredReader wraps a reader.

BytesPer tells the rate per period at which bytes were read since last measurement.

BytesPerSec tells the rate per second at which bytes were read since last measurement.

❖ func (m *MeasuredReader) Read(b []byte) (n int, err error)

Total number of bytes that have been read.

❖ type MeasuredWriter struct { // contains filtered or unexported fields }

MeasuredWriter wraps a writer and tracks how many bytes are written to it.

NewMeasuredWriter wraps a writer.

BytesPer tells the rate per period at which bytes were written since last measurement.

BytesPerSec tells the rate per second at which bytes were written since last measurement.

Total number of bytes that have been written.

❖ func (m *MeasuredWriter) Write(b []byte) (n int, err error)

❖ type ReaderPool struct { // contains filtered or unexported fields }

ReaderPool creates instances of iocontrol.ThrottlerReader that are managed such that they collectively do not exceed a certain rate.

The default value of ReaderPool is not to be used, create instances with `NewReaderPool`.

❖ func NewReaderPool(maxRate int, maxBurst time.Duration) *ReaderPool

NewReaderPool creates a pool that ensures the writers it wraps will respect an overall maxRate, with maxBurst resolution. The semantics of the wrapped writers are the same as those of using a plain ThrottledReader.

❖ func (pool *ReaderPool) Get(r io.Reader) (reader io.Reader, release func())

Get a throttled reader that wraps r.

Len is the number of currently given out throttled readers.

SetRate of the pool, updating each given out reader to respect the newly set rate. Returns the old rate.

❖ type SamplingProfile struct { TimeProfile Reading int Writing int NotReading int NotWriting int }

SamplingProfile samples when a reader and a writer are blocked, or not. If sampled at a high enough resolution, the result should give a good approximation of the distribution of time. The results are not as precise as the result of `Profile`, but the performance overhead is much reduced.

❖ type Throttler interface { // SetRate changes the rate at which the throttler allows reads or writes. SetRate (perSec int) }

❖ type ThrottlerReader interface { io.Reader Throttler }

❖ func ThrottledReader(r io.Reader, bytesPerSec int, maxBurst time.Duration) ThrottlerReader

ThrottledReader ensures that reads to `r` never exceeds a specified rate of bytes per second. The `maxBurst` duration changes how often the verification is done. The smaller the value, the less bursty, but also the more overhead there is to the throttling.

❖ type ThrottlerWriter interface { io.Writer Throttler }

❖ func ThrottledWriter(w io.Writer, bytesPerSec int, maxBurst time.Duration) ThrottlerWriter

ThrottledWriter ensures that writes to `w` never exceeds a specified rate of bytes per second. The `maxBurst` duration changes how often the verification is done. The smaller the value, the less bursty, but also the more overhead there is to the throttling.

❖ type TimeProfile struct { WaitRead time.Duration WaitWrite time.Duration Total time.Duration }

TimeProfile contains information about the timings involved in the exchange of bytes between an io.Writer and io.Reader.

❖ type WriterPool struct { // contains filtered or unexported fields }

WriterPool creates instances of iocontrol.ThrottlerWriter that are managed such that they collectively do not exceed a certain rate.

The default value of WriterPool is not to be used, create instances with `NewWriterPool`.

❖ func NewWriterPool(maxRate int, maxBurst time.Duration) *WriterPool

NewWriterPool creates a pool that ensures the writers it wraps will respect an overall maxRate, with maxBurst resolution. The semantics of the wrapped writers are the same as those of using a plain ThrottledWriter.

❖ func (pool *WriterPool) Get(w io.Writer) (writer io.Writer, release func())

Get a throttled writer that wraps w.

Len is the number of currently given out throttled writers.

SetRate of the pool, updating each given out writer to respect the newly set rate. Returns the old rate.