Created
August 17, 2017 16:48
-
-
Save rickb777/0a6009a92e4b60c0b36fdcdb599de664 to your computer and use it in GitHub Desktop.
Stabbycutyou/accumulator - revised to use templates for many types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Package accumulator is a lightweight wrapper around an atomic.{{.UType}}, which | |
// allows you to easily increment a counter, and "flush" it to 0, returning the | |
// current value. A use case for this might be a timed reading in a stats system. | |
package accumulator | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package accumulator | |
import ( | |
"testing" | |
"time" | |
) | |
func Benchmark{{.UType}}Mutex(b *testing.B) { | |
c := New{{.UType}}() | |
for i := 0; i < b.N; i++ { | |
c.Incr() | |
} | |
} | |
func Test{{.UType}}Mutex(t *testing.T) { | |
c := New{{.UType}}() | |
for i := 0; i < 100; i++ { | |
c.Incr() | |
} | |
if c.Flush() != 100.0 { | |
t.Fail() | |
} | |
} | |
func Benchmark{{.UType}}MutexWithFlush(b *testing.B) { | |
c := New{{.UType}}() | |
for i := 0; i < b.N; i++ { | |
c.Incr() | |
if i%10000 == 0 { | |
c.Flush() | |
} | |
} | |
} | |
func Benchmark{{.UType}}MutexWithConcurrentFlush(b *testing.B) { | |
c := New{{.UType}}() | |
sleep, _ := time.ParseDuration("10ms") | |
go func() { | |
for { | |
time.Sleep(sleep) | |
c.Flush() | |
} | |
}() | |
for i := 0; i < b.N; i++ { | |
c.Incr() | |
if i%10000 == 0 { | |
c.Flush() | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package accumulator | |
import ( | |
"sync" | |
) | |
// {{.UType}} is a wrapper around a *{{.Type}}, interacted with via the atomic package | |
type {{.UType}} struct { | |
l sync.Mutex | |
n {{.Type}} | |
} | |
// New{{.UType}} returns a new pointer to an accumulator | |
func New{{.UType}}() *{{.UType}} { | |
return &{{.UType}}{n: 0} | |
} | |
// Incr incremenets the accumulator by 1 | |
func (i *{{.UType}}) Incr() { | |
i.l.Lock() | |
i.n++ | |
i.l.Unlock() | |
} | |
// IncrN incremenets the accumulator by 1 | |
func (i *{{.UType}}) IncrN(n {{.Type}}) { | |
i.l.Lock() | |
i.n += n | |
i.l.Unlock() | |
} | |
// Flush resets the accumulator to 0, and returns the former value | |
func (i *{{.UType}}) Flush() {{.Type}} { | |
i.l.Lock() | |
n := i.n | |
i.n = 0 | |
i.l.Unlock() | |
return n | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package accumulator | |
import ( | |
"testing" | |
"time" | |
) | |
func BenchmarkAtomic{{.UType}}(b *testing.B) { | |
c := New{{.UType}}() | |
for i := 0; i < b.N; i++ { | |
c.Incr() | |
} | |
} | |
func TestAtomic{{.UType}}(t *testing.T) { | |
c := New{{.UType}}() | |
for i := 0; i < 100; i++ { | |
c.Incr() | |
} | |
if c.Flush() != 100 { | |
t.Fail() | |
} | |
} | |
func BenchmarkAtomic{{.UType}}WithFlush(b *testing.B) { | |
c := New{{.UType}}() | |
for i := 0; i < b.N; i++ { | |
c.Incr() | |
if i%10000 == 0 { | |
c.Flush() | |
} | |
} | |
} | |
func BenchmarkAtomic{{.UType}}WithConcurrentFlush(b *testing.B) { | |
c := New{{.UType}}() | |
sleep, _ := time.ParseDuration("10ms") | |
go func() { | |
for { | |
time.Sleep(sleep) | |
c.Flush() | |
} | |
}() | |
for i := 0; i < b.N; i++ { | |
c.Incr() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package accumulator | |
import ( | |
"sync/atomic" | |
) | |
// {{.UType}} is a wrapper around an *{{.Type}}, interacted with via the atomic package | |
type {{.UType}} struct { | |
n *{{.Type}} | |
} | |
// New{{.UType}} returns a new pointer to an accumulator | |
func New{{.UType}}() *{{.UType}} { | |
i := {{.Type}}(0) | |
return &{{.UType}}{n: &i} | |
} | |
// Incr incremenets the accumulator by 1 | |
func (i *{{.UType}}) Incr() { | |
atomic.Add{{.UType}}(i.n, 1) | |
} | |
// IncrN incremenets the accumulator by the provided value n | |
func (i *{{.UType}}) IncrN(n {{.Type}}) { | |
atomic.Add{{.UType}}(i.n, n) | |
} | |
// Flush resets the accumulator to 0, and returns the former value | |
func (i *{{.UType}}) Flush() {{.Type}} { | |
return atomic.Swap{{.UType}}(i.n, 0) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# first, run | |
# go get github.com/rickb777/runtemplate | |
default: | |
runtemplate -tpl intAccumulator.tpl Type=int64 | |
runtemplate -tpl intAccumulator.tpl Type=uint64 | |
runtemplate -tpl intAccumulator.tpl Type=int32 | |
runtemplate -tpl intAccumulator.tpl Type=uint32 | |
runtemplate -tpl int_test.tpl Type=int32 | |
runtemplate -tpl int_test.tpl Type=int64 | |
runtemplate -tpl int_test.tpl Type=uint32 | |
runtemplate -tpl int_test.tpl Type=uint64 | |
runtemplate -tpl floatAccumulator.tpl Type=float32 | |
runtemplate -tpl floatAccumulator.tpl Type=float64 | |
runtemplate -tpl float_test.tpl Type=float32 | |
runtemplate -tpl float_test.tpl Type=float64 | |
clean: | |
rm -f *accumulator.go *_test.go | |
.PHONY: clean default |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment