From ce7283ae1b180452558bd5563e6c7aef52b1a4bd Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Tue, 19 Sep 2017 15:52:42 -0500 Subject: [PATCH 1/6] convert to RWMutex in index, holder, view, and frame use RLock and RUnlock in mapperLocal hotpath --- frame.go | 10 +++++----- holder.go | 6 +++--- index.go | 6 +++--- view.go | 6 +++--- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/frame.go b/frame.go index f9580cc6b..2fcb0c47d 100644 --- a/frame.go +++ b/frame.go @@ -43,7 +43,7 @@ const ( // Frame represents a container for views. type Frame struct { - mu sync.Mutex + mu sync.RWMutex path string index string name string @@ -404,8 +404,8 @@ func (f *Frame) Close() error { // Schema returns the frame's current schema. func (f *Frame) Schema() *FrameSchema { - f.mu.Lock() - defer f.mu.Unlock() + f.mu.RLock() + defer f.mu.RUnlock() return f.schema } @@ -506,8 +506,8 @@ func (f *Frame) ViewPath(name string) string { // View returns a view in the frame by name. func (f *Frame) View(name string) *View { - f.mu.Lock() - defer f.mu.Unlock() + f.mu.RLock() + defer f.mu.RUnlock() return f.view(name) } diff --git a/holder.go b/holder.go index 4270c2594..0cf5f6901 100644 --- a/holder.go +++ b/holder.go @@ -38,7 +38,7 @@ const ( // Holder represents a container for indexes. type Holder struct { - mu sync.Mutex + mu sync.RWMutex // Indexes by name. indexes map[string]*Index @@ -183,8 +183,8 @@ func (h *Holder) IndexPath(name string) string { return filepath.Join(h.Path, na // Index returns the index by name. func (h *Holder) Index(name string) *Index { - h.mu.Lock() - defer h.mu.Unlock() + h.mu.RLock() + defer h.mu.RUnlock() return h.index(name) } diff --git a/index.go b/index.go index 345215690..5c7e06f05 100644 --- a/index.go +++ b/index.go @@ -37,7 +37,7 @@ const ( // Index represents a container for frames. type Index struct { - mu sync.Mutex + mu sync.RWMutex path string name string @@ -345,8 +345,8 @@ func (i *Index) InputDefinitionPath() string { // Frame returns a frame in the index by name. func (i *Index) Frame(name string) *Frame { - i.mu.Lock() - defer i.mu.Unlock() + i.mu.RLock() + defer i.mu.RUnlock() return i.frame(name) } diff --git a/view.go b/view.go index 2d5b7d776..3f5a61437 100644 --- a/view.go +++ b/view.go @@ -43,7 +43,7 @@ func IsValidView(name string) bool { // View represents a container for frame data. type View struct { - mu sync.Mutex + mu sync.RWMutex path string index string frame string @@ -194,8 +194,8 @@ func (v *View) FragmentPath(slice uint64) string { // Fragment returns a fragment in the view by slice. func (v *View) Fragment(slice uint64) *Fragment { - v.mu.Lock() - defer v.mu.Unlock() + v.mu.RLock() + defer v.mu.RUnlock() return v.fragment(slice) } From 023dbbcdfd99dddf3e0a39f00415cc419b6a8658 Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Tue, 19 Sep 2017 16:03:10 -0500 Subject: [PATCH 2/6] make index column label and options RLocks --- index.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/index.go b/index.go index 5c7e06f05..93100e1da 100644 --- a/index.go +++ b/index.go @@ -129,12 +129,26 @@ func (i *Index) SetColumnLabel(v string) error { // ColumnLabel returns the column label. func (i *Index) ColumnLabel() string { - i.mu.Lock() + i.mu.RLock() v := i.columnLabel - i.mu.Unlock() + i.mu.RUnlock() return v } +// Options returns all options for this index. +func (i *Index) Options() IndexOptions { + i.mu.RLock() + defer i.mu.RUnlock() + return i.options() +} + +func (i *Index) options() IndexOptions { + return IndexOptions{ + ColumnLabel: i.columnLabel, + TimeQuantum: i.timeQuantum, + } +} + // Open opens and initializes the index. func (i *Index) Open() error { // Ensure the path exists. From 1210489f76089da9b1f4895fc12af4f9cf318f2b Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Tue, 19 Sep 2017 16:11:06 -0500 Subject: [PATCH 3/6] frame rowlabel and options read-only lock --- frame.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frame.go b/frame.go index 2fcb0c47d..d52cb8fe1 100644 --- a/frame.go +++ b/frame.go @@ -166,9 +166,9 @@ func (f *Frame) SetRowLabel(v string) error { // RowLabel returns the row label. func (f *Frame) RowLabel() string { - f.mu.Lock() + f.mu.RLock() v := f.rowLabel - f.mu.Unlock() + f.mu.RUnlock() return v } @@ -217,8 +217,8 @@ func (f *Frame) CacheSize() uint32 { // Options returns all options for this frame. func (f *Frame) Options() FrameOptions { - f.mu.Lock() - defer f.mu.Unlock() + f.mu.RLock() + defer f.mu.RUnlock() return f.options() } From c5b6c39c56cdf1b878ebe1d8a8c767899af050f3 Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Tue, 19 Sep 2017 16:24:05 -0500 Subject: [PATCH 4/6] read only lock in fragment.FieldSum --- fragment.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fragment.go b/fragment.go index 4fa13e70e..35bd4c7be 100644 --- a/fragment.go +++ b/fragment.go @@ -67,7 +67,7 @@ const ( // Fragment represents the intersection of a frame and slice in an index. type Fragment struct { - mu sync.Mutex + mu sync.RWMutex // Composite identifiers index string @@ -545,8 +545,8 @@ func (f *Fragment) SetFieldValue(columnID uint64, bitDepth uint, value uint64) ( // FieldSum returns the sum of a given field as well as the number of columns involved. // A bitmap can be passed in to optionally filter the computed columns. func (f *Fragment) FieldSum(filter *Bitmap, bitDepth uint) (sum, count uint64, err error) { - f.mu.Lock() - defer f.mu.Unlock() + f.mu.RLock() + defer f.mu.RUnlock() // Compute count based on the existance bit. row := f.row(uint64(bitDepth), true, true) From 3aecb612854b95cbcc9559617e36dc323e362e98 Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Tue, 19 Sep 2017 16:30:37 -0500 Subject: [PATCH 5/6] more read-only locking for maxslice, timequantum, and Index.Frames --- frame.go | 8 ++++---- index.go | 16 ++++++++-------- view.go | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/frame.go b/frame.go index d52cb8fe1..1d6867746 100644 --- a/frame.go +++ b/frame.go @@ -113,8 +113,8 @@ func (f *Frame) RowAttrStore() *AttrStore { return f.rowAttrStore } // MaxSlice returns the max slice in the frame. func (f *Frame) MaxSlice() uint64 { - f.mu.Lock() - defer f.mu.Unlock() + f.mu.RLock() + defer f.mu.RUnlock() var max uint64 for _, view := range f.views { @@ -129,8 +129,8 @@ func (f *Frame) MaxSlice() uint64 { // MaxInverseSlice returns the max inverse slice in the frame. func (f *Frame) MaxInverseSlice() uint64 { - f.mu.Lock() - defer f.mu.Unlock() + f.mu.RLock() + defer f.mu.RUnlock() view := f.views[ViewInverse] if view == nil { diff --git a/index.go b/index.go index 93100e1da..256c44184 100644 --- a/index.go +++ b/index.go @@ -276,8 +276,8 @@ func (i *Index) MaxSlice() uint64 { if i == nil { return 0 } - i.mu.Lock() - defer i.mu.Unlock() + i.mu.RLock() + defer i.mu.RUnlock() max := i.remoteMaxSlice for _, f := range i.frames { @@ -302,8 +302,8 @@ func (i *Index) MaxInverseSlice() uint64 { if i == nil { return 0 } - i.mu.Lock() - defer i.mu.Unlock() + i.mu.RLock() + defer i.mu.RUnlock() max := i.remoteMaxInverseSlice for _, f := range i.frames { @@ -323,8 +323,8 @@ func (i *Index) SetRemoteMaxInverseSlice(v uint64) { // TimeQuantum returns the default time quantum for the index. func (i *Index) TimeQuantum() TimeQuantum { - i.mu.Lock() - defer i.mu.Unlock() + i.mu.RLock() + defer i.mu.RUnlock() return i.timeQuantum } @@ -380,8 +380,8 @@ func (i *Index) inputDefinition(name string) *InputDefinition { return i.inputDe // Frames returns a list of all frames in the index. func (i *Index) Frames() []*Frame { - i.mu.Lock() - defer i.mu.Unlock() + i.mu.RLock() + defer i.mu.RUnlock() a := make([]*Frame, 0, len(i.frames)) for _, f := range i.frames { diff --git a/view.go b/view.go index 3f5a61437..e9bbb9c5f 100644 --- a/view.go +++ b/view.go @@ -174,8 +174,8 @@ func (v *View) Close() error { // MaxSlice returns the max slice in the view. func (v *View) MaxSlice() uint64 { - v.mu.Lock() - defer v.mu.Unlock() + v.mu.RLock() + defer v.mu.RUnlock() var max uint64 for slice := range v.fragments { From f257be992620f2d86130e0f88416452be7cea9a9 Mon Sep 17 00:00:00 2001 From: Matthew Jaffee Date: Tue, 19 Sep 2017 21:37:35 -0500 Subject: [PATCH 6/6] FieldSum calls fragment.row which needs write lock remove read lock and call fragment.Row --- fragment.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/fragment.go b/fragment.go index 35bd4c7be..18e2cf1b5 100644 --- a/fragment.go +++ b/fragment.go @@ -545,11 +545,8 @@ func (f *Fragment) SetFieldValue(columnID uint64, bitDepth uint, value uint64) ( // FieldSum returns the sum of a given field as well as the number of columns involved. // A bitmap can be passed in to optionally filter the computed columns. func (f *Fragment) FieldSum(filter *Bitmap, bitDepth uint) (sum, count uint64, err error) { - f.mu.RLock() - defer f.mu.RUnlock() - // Compute count based on the existance bit. - row := f.row(uint64(bitDepth), true, true) + row := f.Row(uint64(bitDepth)) if filter != nil { row = row.Intersect(filter) } @@ -563,7 +560,7 @@ func (f *Fragment) FieldSum(filter *Bitmap, bitDepth uint) (sum, count uint64, e // 10*(2^0) + 4*(2^1) + 3*(2^2) = 30 // for i := uint(0); i < bitDepth; i++ { - row := f.row(uint64(i), true, true) + row := f.Row(uint64(i)) if filter != nil { row = row.Intersect(filter) }