Skip to content

Commit

Permalink
feat: Catches up minor performance improvements and adds a build tag …
Browse files Browse the repository at this point in the history
…to build without mutex use

when the user knows there will be no multiple access from go routines

Signed-off-by: Jim.Idle <jimi@idle.ws>
  • Loading branch information
jimidle authored and parrt committed May 15, 2024
1 parent 41b9360 commit 057bd36
Show file tree
Hide file tree
Showing 10 changed files with 69 additions and 24 deletions.
2 changes: 0 additions & 2 deletions runtime/Go/antlr/go.sum

This file was deleted.

8 changes: 3 additions & 5 deletions runtime/Go/antlr/v4/atn.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

package antlr

import "sync"

// ATNInvalidAltNumber is used to represent an ALT number that has yet to be calculated or
// which is invalid for a particular struct such as [*antlr.BaseRuleContext]
var ATNInvalidAltNumber int
Expand Down Expand Up @@ -56,9 +54,9 @@ type ATN struct {
//
states []ATNState

mu sync.Mutex
stateMu sync.RWMutex
edgeMu sync.RWMutex
mu Mutex
stateMu RWMutex
edgeMu RWMutex
}

// NewATN returns a new ATN struct representing the given grammarType and is used
Expand Down
3 changes: 0 additions & 3 deletions runtime/Go/antlr/v4/atn_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ func NewATNConfig1(c *ATNConfig, state ATNState, context *PredictionContext) *AT
// NewATNConfig creates a new ATNConfig instance given an existing config, a state, a context and a semantic context, other 'constructors'
// are just wrappers around this one.
func NewATNConfig(c *ATNConfig, state ATNState, context *PredictionContext, semanticContext SemanticContext) *ATNConfig {
if semanticContext == nil {
panic("semanticContext cannot be nil") // TODO: Remove this - probably put here for some bug that is now fixed
}
b := &ATNConfig{}
b.InitATNConfig(c, state, c.GetAlt(), context, semanticContext)
b.cType = parserConfig
Expand Down
5 changes: 2 additions & 3 deletions runtime/Go/antlr/v4/jcollect.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"container/list"
"runtime/debug"
"sort"
"sync"
)

// Collectable is an interface that a struct should implement if it is to be
Expand Down Expand Up @@ -587,12 +586,12 @@ type VisitRecord struct {

type VisitList struct {
cache *list.List
lock sync.RWMutex
lock RWMutex
}

var visitListPool = VisitList{
cache: list.New(),
lock: sync.RWMutex{},
lock: RWMutex{},
}

// NewVisitRecord returns a new VisitRecord instance from the pool if available.
Expand Down
1 change: 1 addition & 0 deletions runtime/Go/antlr/v4/ll1_analyzer.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ func (la *LL1Analyzer) getDecisionLookahead(s ATNState) []*IntervalSet {
for alt := 0; alt < count; alt++ {

look[alt] = NewIntervalSet()
// TODO: This is one of the reasons that ATNConfigs are allocated and freed all the time - fix this tomorrow jim!
lookBusy := NewJStore[*ATNConfig, Comparator[*ATNConfig]](aConfEqInst, ClosureBusyCollection, "LL1Analyzer.getDecisionLookahead for lookBusy")
la.look1(s.GetTransitions()[alt].getTarget(), nil, BasePredictionContextEMPTY, look[alt], lookBusy, NewBitSet(), false, false)

Expand Down
9 changes: 6 additions & 3 deletions runtime/Go/antlr/v4/mutex.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
// +build !nomutex
//go:build !antlr.nomutex
// +build !antlr.nomutex

package antlr

import "sync"

// Mutex is a simple mutex implementation which just delegates to sync.Mutex, it
// is used to provide a mutex implementation for the antlr package, which users
// can turn off with the build tag -tags antlr.nomutex
type Mutex struct {
mu sync.Mutex
}
Expand All @@ -16,7 +20,6 @@ func (m *Mutex) Unlock() {
m.mu.Unlock()
}


type RWMutex struct {
mu sync.RWMutex
}
Expand All @@ -35,4 +38,4 @@ func (m *RWMutex) RLock() {

func (m *RWMutex) RUnlock() {
m.mu.RUnlock()
}
}
2 changes: 1 addition & 1 deletion runtime/Go/antlr/v4/mutex_nomutex.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build nomutex
// +build antlr.nomutex

package antlr

Expand Down
7 changes: 2 additions & 5 deletions runtime/Go/antlr/v4/prediction_context.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package antlr

import (
"fmt"
"golang.org/x/exp/slices"
"strconv"
)

Expand Down Expand Up @@ -144,10 +143,8 @@ func (p *PredictionContext) ArrayEquals(o Collectable[*PredictionContext]) bool

// Must compare the actual array elements and not just the array address
//
return slices.Equal(p.returnStates, other.returnStates) &&
slices.EqualFunc(p.parents, other.parents, func(x, y *PredictionContext) bool {
return x.Equals(y)
})
return intSlicesEqual(p.returnStates, other.returnStates) &&
pcSliceEqual(p.parents, other.parents)
}

func (p *PredictionContext) SingletonEquals(other Collectable[*PredictionContext]) bool {
Expand Down
3 changes: 1 addition & 2 deletions runtime/Go/antlr/v4/statistics.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"path/filepath"
"sort"
"strconv"
"sync"
)

// This file allows the user to collect statistics about the runtime of the ANTLR runtime. It is not enabled by default
Expand All @@ -30,7 +29,7 @@ type goRunStats struct {
// within this package.
//
jStats []*JStatRec
jStatsLock sync.RWMutex
jStatsLock `RWMutex
topN int
topNByMax []*JStatRec
topNByUsed []*JStatRec
Expand Down
53 changes: 53 additions & 0 deletions runtime/Go/antlr/v4/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,56 @@ func isDirectory(dir string) (bool, error) {
}
return fileInfo.IsDir(), err
}

// intSlicesEqual returns true if the two slices of ints are equal, and is a little
// faster than slices.Equal.
func intSlicesEqual(s1, s2 []int) bool {
if s1 == nil && s2 == nil {
return true
}
if s1 == nil || s2 == nil {
return false
}
if len(s1) == 0 && len(s2) == 0 {
return true
}

if len(s1) == 0 || len(s2) == 0 || len(s1) != len(s2) {
return false
}
// If the slices are using the same memory, then they are the same slice
if &s1[0] == &s2[0] {
return true
}
for i, v := range s1 {
if v != s2[i] {
return false
}
}
return true
}

func pcSliceEqual(s1, s2 []*PredictionContext) bool {
if s1 == nil && s2 == nil {
return true
}
if s1 == nil || s2 == nil {
return false
}
if len(s1) == 0 && len(s2) == 0 {
return true
}
if len(s1) == 0 || len(s2) == 0 || len(s1) != len(s2) {
return false
}
// If the slices are using the same memory, then they are the same slice
if &s1[0] == &s2[0] {
return true
}
for i, v := range s1 {
if !v.Equals(s2[i]) {
return false
}
}
return true
}

0 comments on commit 057bd36

Please sign in to comment.