Skip to content

Commit

Permalink
Merge pull request #21 from stevekuznetsov/skuznets/efficient-seriali…
Browse files Browse the repository at this point in the history
…zation

minimize allocations when deserializing
  • Loading branch information
postwait authored Jun 4, 2021
2 parents f7783f4 + 463fcc4 commit ed0377b
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 27 deletions.
8 changes: 4 additions & 4 deletions api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,31 +100,31 @@ func TestQuantiles(t *testing.T) {
}

func BenchmarkHistogramRecordValue(b *testing.B) {
h := hist.NewNoLocks()
h := hist.New(hist.NoLocks())
for i := 0; i < b.N; i++ {
h.RecordValue(float64(i % 1000))
}
b.ReportAllocs()
}

func BenchmarkHistogramTypical(b *testing.B) {
h := hist.NewNoLocks()
h := hist.New(hist.NoLocks())
for i := 0; i < b.N; i++ {
h.RecordValue(float64(i % 1000))
}
b.ReportAllocs()
}

func BenchmarkHistogramRecordIntScale(b *testing.B) {
h := hist.NewNoLocks()
h := hist.New(hist.NoLocks())
for i := 0; i < b.N; i++ {
h.RecordIntScale(int64(i%90+10), (i/1000)%3)
}
b.ReportAllocs()
}

func BenchmarkHistogramTypicalIntScale(b *testing.B) {
h := hist.NewNoLocks()
h := hist.New(hist.NoLocks())
for i := 0; i < b.N; i++ {
h.RecordIntScale(int64(i%90+10), (i/1000)%3)
}
Expand Down
77 changes: 54 additions & 23 deletions circonusllhist.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ func getBytesRequired(val uint64) (len int8) {
return int8(BVL1)
}

func writeBin(out io.Writer, in bin, idx int) (err error) {
func writeBin(out io.Writer, in bin) (err error) {

err = binary.Write(out, binary.BigEndian, in.val)
if err != nil {
Expand Down Expand Up @@ -350,17 +350,13 @@ func readBin(in io.Reader) (out bin, err error) {
}

func Deserialize(in io.Reader) (h *Histogram, err error) {
h = New()
if h.bvs == nil {
h.bvs = make([]bin, 0, defaultHistSize)
}

var nbin int16
err = binary.Read(in, binary.BigEndian, &nbin)
if err != nil {
return
}

h = New(Size(uint16(nbin)))
for ii := int16(0); ii < nbin; ii++ {
bb, err := readBin(in)
if err != nil {
Expand All @@ -372,15 +368,22 @@ func Deserialize(in io.Reader) (h *Histogram, err error) {
}

func (h *Histogram) Serialize(w io.Writer) error {
var nbin int16
for i := range h.bvs {
if h.bvs[i].count != 0 {
nbin += 1
}
}

var nbin int16 = int16(len(h.bvs))
if err := binary.Write(w, binary.BigEndian, nbin); err != nil {
return err
}

for i := 0; i < len(h.bvs); i++ {
if err := writeBin(w, h.bvs[i], i); err != nil {
return err

for _, bv := range h.bvs {
if bv.count != 0 {
if err := writeBin(w, bv); err != nil {
return err
}
}
}
return nil
Expand All @@ -400,26 +403,54 @@ func (h *Histogram) SerializeB64(w io.Writer) error {
return encoder.Close()
}

// New returns a new Histogram
func New() *Histogram {
return &Histogram{
allocd: defaultHistSize,
used: 0,
bvs: make([]bin, defaultHistSize),
useLocks: true,
// Options are exposed options for initializing a histogram
type Options struct {
// Size is the number of bins.
Size uint16

// UseLocks determines if the histogram should use locks
UseLocks bool
}

// Option knows how to mutate the Options to change initialization
type Option func(*Options)

// NoLocks configures a histogram to not use locks
func NoLocks() Option {
return func(options *Options) {
options.UseLocks = false
}
}

// New returns a Histogram without locking
func NewNoLocks() *Histogram {
// Size configures a histogram to use a specific number of bins
func Size(size uint16) Option {
return func(options *Options) {
options.Size = size
}
}

// New returns a new Histogram, respecting the passed Options.
func New(options ...Option) *Histogram {
o := Options{
Size: defaultHistSize,
UseLocks: true,
}
for _, opt := range options {
opt(&o)
}
return &Histogram{
allocd: defaultHistSize,
allocd: o.Size,
used: 0,
bvs: make([]bin, defaultHistSize),
useLocks: false,
bvs: make([]bin, o.Size),
useLocks: o.UseLocks,
}
}

// Deprecated: use New(NoLocks()) instead
func NewNoLocks() *Histogram {
return New(NoLocks())
}

// NewFromStrings returns a Histogram created from DecStrings strings
func NewFromStrings(strs []string, locks bool) (*Histogram, error) {

Expand Down

0 comments on commit ed0377b

Please sign in to comment.