From 07273b8b311ce75ea5e54bccc3688b7514aab0b0 Mon Sep 17 00:00:00 2001 From: charlie <3140647@qq.com> Date: Thu, 2 Jun 2022 13:46:21 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AD=97=E7=AC=A6=E4=B8=B2=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E7=BC=93=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiled_buffer/compiled_buffer.go | 46 +++++++++++++++++++++++ compiled_buffer/compiled_buffer_test.go | 49 +++++++++++++++++++++++++ 2 files changed, 95 insertions(+) create mode 100644 compiled_buffer/compiled_buffer.go create mode 100644 compiled_buffer/compiled_buffer_test.go diff --git a/compiled_buffer/compiled_buffer.go b/compiled_buffer/compiled_buffer.go new file mode 100644 index 0000000..e84157e --- /dev/null +++ b/compiled_buffer/compiled_buffer.go @@ -0,0 +1,46 @@ +package compiledbuffer + +import "sync" + +type compiledbuffer[T any] struct { + buf map[string]T + compileFunc func(string) (T, error) + mu sync.RWMutex +} + +func NewCompiledBuffer[T any](fn func(string) (T, error)) *compiledbuffer[T] { + return &compiledbuffer[T]{ + buf: make(map[string]T), + compileFunc: fn, + } +} + +func (x *compiledbuffer[T]) Put(s string) (T, error) { + p, err := x.compileFunc(s) + if err != nil { + return p, err + } + + x.mu.Lock() + x.buf[s] = p + x.mu.Unlock() + + return p, nil +} + +func (x *compiledbuffer[T]) Get(s string) (T, error) { + x.mu.RLock() + if p, ok := x.buf[s]; ok { + x.mu.RUnlock() + return p, nil + } + x.mu.RUnlock() + + return x.Put(s) +} + +func (x *compiledbuffer[T]) Clear() { + x.mu.Lock() + x.buf = make(map[string]T) + x.mu.Unlock() +} diff --git a/compiled_buffer/compiled_buffer_test.go b/compiled_buffer/compiled_buffer_test.go new file mode 100644 index 0000000..d8a2b0e --- /dev/null +++ b/compiled_buffer/compiled_buffer_test.go @@ -0,0 +1,49 @@ +package compiledbuffer + +import ( + "regexp" + "strconv" + "sync/atomic" + "testing" +) + +var s = "^aaa^" + +func TestPutGet(t *testing.T) { + b := NewCompiledBuffer(func(s string) (*regexp.Regexp, error) { return regexp.Compile(s) }) + + t.Log(b.Put(s)) + r, _ := b.Get(s) + + t.Log(r.Match([]byte("abc"))) +} + +func BenchmarkGet(b *testing.B) { + b.Run("buf", func(b *testing.B) { + buf := NewCompiledBuffer(func(s string) (*regexp.Regexp, error) { return regexp.Compile(s) }) + buf.Put(s) + + for i := 0; i < b.N; i++ { + buf.Get(s) + } + }) + + b.Run("buf", func(b *testing.B) { + for i := 0; i < b.N; i++ { + regexp.Compile(s) + } + }) +} + +func BenchmarkConcurrence(b *testing.B) { + buf := NewCompiledBuffer(func(s string) (*regexp.Regexp, error) { return regexp.Compile(s) }) + var i int64 + + b.RunParallel(func(p *testing.PB) { + gid := int(atomic.AddInt64(&i, 1) - 1) + + for i := 0; p.Next(); i++ { + buf.Get(strconv.Itoa(gid)) + } + }) +}