mini micro optimizations

This commit is contained in:
Arpad Ryszka 2017-07-30 02:35:51 +02:00
parent ff26b83b95
commit 1b21b8fde2
7 changed files with 142 additions and 91 deletions

12
.gitignore vendored
View File

@ -1,14 +1,2 @@
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/

View File

@ -14,4 +14,15 @@ check: build
fmt: $(SOURCES)
@gofmt -w -s $(SOURCES)
cpu.out: $(SOURCES)
go test -v -run TestMMLFile -cpuprofile cpu.out
cpu: cpu.out
go tool pprof -top cpu.out
precommit: fmt build check
clean:
@rm -f *.test
@rm -f cpu.out
@go clean -i ./...

19
char.go
View File

@ -68,6 +68,22 @@ func (p *charParser) match(t rune) bool {
return p.not
}
func (p *charParser) matchBuild(t rune) bool {
for _, ci := range p.chars {
if ci == t {
return !p.not
}
}
for _, ri := range p.ranges {
if t >= ri[0] && t <= ri[1] {
return !p.not
}
}
return p.not
}
func (p *charParser) parse(t Trace, c *context) {
// t = t.Extend(p.name)
// t.Out1("parsing", c.offset)
@ -86,12 +102,13 @@ func (p *charParser) parse(t Trace, c *context) {
}
func (p *charParser) build(c *context) ([]*Node, bool) {
// TODO: how to remove this check
t, ok := c.token()
if !ok {
panic("damaged parser context")
}
if !p.match(t) {
if !p.matchBuild(t) {
return nil, false
}

View File

@ -22,7 +22,7 @@ type choiceBuilder struct {
id int
commit CommitType
elements []builder
includedBy []int
includedBy *idSet
}
func newChoice(name string, ct CommitType, elements []string) *choiceDefinition {
@ -44,6 +44,7 @@ func (d *choiceDefinition) init(r *registry) error {
name: d.name,
id: d.id,
commit: d.commit,
includedBy: &idSet{},
}
}
@ -73,10 +74,11 @@ func (d *choiceDefinition) setIncludedBy(r *registry, includedBy int, parsers *i
name: d.name,
id: d.id,
commit: d.commit,
includedBy: &idSet{},
}
}
d.cbuilder.includedBy = appendIfMissing(d.cbuilder.includedBy, includedBy)
d.cbuilder.includedBy.set(includedBy)
parsers.set(d.id)
return setItemsIncludedBy(r, d.elements, includedBy, parsers)
@ -134,6 +136,7 @@ func (d *choiceDefinition) builder() builder {
name: d.name,
id: d.id,
commit: d.commit,
includedBy: &idSet{},
}
}
@ -172,9 +175,10 @@ func (p *choiceParser) parse(t Trace, c *context) {
var match bool
var nextTo int
var elementIndex int
var foundMatch bool
for {
var foundMatch bool
foundMatch = false
elementIndex = 0
for elementIndex < len(p.elements) {
@ -222,19 +226,14 @@ func (b *choiceBuilder) nodeName() string { return b.name }
func (b *choiceBuilder) nodeID() int { return b.id }
func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
to, ok := c.store.takeMatch(c.offset, b.id)
to, ok := c.store.takeMatch(c.offset, b.id, b.includedBy)
if !ok {
return nil, false
}
for _, ib := range b.includedBy {
c.store.takeMatchLength(c.offset, ib, to)
}
var element builder
for _, e := range b.elements {
elementTo, match, _ := c.store.getMatch(c.offset, e.nodeID())
if match && elementTo == to {
if c.store.hasMatchTo(c.offset, e.nodeID(), to) {
element = e
break
}

View File

@ -90,13 +90,21 @@ func (c *context) exclude(offset int, id int) {
}
}
for i := range c.isExcluded[id] {
if c.isExcluded[id][i] == -1 {
c.isExcluded[id][i] = offset
return
}
}
c.isExcluded[id] = append(c.isExcluded[id], offset)
}
func (c *context) include(offset int, id int) {
for i := range c.isExcluded[id] {
if c.isExcluded[id][i] == offset {
c.isExcluded[id] = append(c.isExcluded[id][:i], c.isExcluded[id][i+1:]...)
// c.isExcluded[id] = append(c.isExcluded[id][:i], c.isExcluded[id][i+1:]...)
c.isExcluded[id][i] = -1
break
}
}

View File

@ -25,7 +25,8 @@ type sequenceBuilder struct {
commit CommitType
items []builder
ranges [][]int
includedBy []int
includedBy *idSet
allChars bool
}
func newSequence(name string, ct CommitType, items []SequenceItem) *sequenceDefinition {
@ -51,9 +52,11 @@ func (d *sequenceDefinition) init(r *registry) error {
name: d.name,
id: d.id,
commit: d.commit,
includedBy: &idSet{},
}
}
allChars := true
for _, item := range d.items {
if item.Min == 0 && item.Max == 0 {
item.Min, item.Max = 1, 1
@ -69,9 +72,16 @@ func (d *sequenceDefinition) init(r *registry) error {
}
d.sbuilder.items = append(d.sbuilder.items, def.builder())
if allChars {
if _, isChar := def.(*charParser); !isChar {
allChars = false
}
}
}
d.sbuilder.ranges = d.ranges
d.sbuilder.allChars = allChars
if !d.includeItems() {
return nil
@ -94,10 +104,11 @@ func (d *sequenceDefinition) setIncludedBy(r *registry, includedBy int, parsers
name: d.name,
id: d.id,
commit: d.commit,
includedBy: &idSet{},
}
}
d.sbuilder.includedBy = appendIfMissing(d.sbuilder.includedBy, includedBy)
d.sbuilder.includedBy.set(includedBy)
if !d.includeItems() {
return nil
@ -161,6 +172,7 @@ func (d *sequenceDefinition) builder() builder {
name: d.name,
id: d.id,
commit: d.commit,
includedBy: &idSet{},
}
}
@ -186,16 +198,13 @@ func (p *sequenceParser) parse(t Trace, c *context) {
return
}
// if c.store.hasNoMatch(c.offset, p.id) {
// c.fail(c.offset)
// }
c.exclude(c.offset, p.id)
itemIndex := 0
var currentCount int
from := c.offset
to := c.offset
var parsed bool
for itemIndex < len(p.items) {
// TODO: is it ok to parse before max range check? what if max=0
@ -214,7 +223,7 @@ func (p *sequenceParser) parse(t Trace, c *context) {
continue
}
parsed := c.offset > to
parsed = c.offset > to
if parsed {
currentCount++
}
@ -244,13 +253,24 @@ func (b *sequenceBuilder) nodeName() string { return b.name }
func (b *sequenceBuilder) nodeID() int { return b.id }
func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
to, ok := c.store.takeMatch(c.offset, b.id)
to, ok := c.store.takeMatch(c.offset, b.id, b.includedBy)
if !ok {
return nil, false
}
for _, ib := range b.includedBy {
c.store.takeMatchLength(c.offset, ib, to)
if b.allChars {
from := c.offset
c.offset = to
if b.commit&Alias != 0 {
return nil, true
}
return []*Node{{
Name: b.name,
From: from,
To: to,
tokens: c.tokens,
}}, true
}
from := c.offset

View File

@ -10,16 +10,8 @@ type store struct {
match [][]int
}
func (s *store) hasNoMatch(offset, id int) bool {
if len(s.noMatch) <= offset || s.noMatch[offset] == nil {
return false
}
return s.noMatch[offset].has(id)
}
func (s *store) getMatch(offset, id int) (int, bool, bool) {
if s.hasNoMatch(offset, id) {
if len(s.noMatch) > offset && s.noMatch[offset] != nil && s.noMatch[offset].has(id) {
return 0, false, true
}
@ -46,11 +38,29 @@ func (s *store) getMatch(offset, id int) (int, bool, bool) {
return to, found, found
}
func (s *store) takeMatch(offset, id int) (int, bool) {
if s.hasNoMatch(offset, id) {
return 0, false
func (s *store) hasMatchTo(offset, id, to int) bool {
if len(s.noMatch) > offset && s.noMatch[offset] != nil && s.noMatch[offset].has(id) {
return false
}
if len(s.match) <= offset {
return false
}
for i := 0; i < len(s.match[offset]); i += 2 {
if s.match[offset][i] != id {
continue
}
if s.match[offset][i+1] == to {
return true
}
}
return false
}
func (s *store) takeMatch(offset, id int, includedBy *idSet) (int, bool) {
if len(s.match) <= offset {
return 0, false
}
@ -75,43 +85,27 @@ func (s *store) takeMatch(offset, id int) (int, bool) {
if found {
s.match[offset][index] = -1
for i := 0; i < len(s.match[offset]); i += 2 {
if includedBy.has(s.match[offset][i]) && s.match[offset][i+1] == to {
s.match[offset][i] = -1
}
}
}
return to, found
}
func (s *store) takeMatchLength(offset, id, to int) (int, bool) {
if s.hasNoMatch(offset, id) {
return 0, false
}
func (s *store) takeMatchLength(offset, id, to int) {
if len(s.match) <= offset {
return 0, false
return
}
var (
found bool
// index int
)
for i := 0; i < len(s.match[offset]); i += 2 {
if s.match[offset][i] != id {
continue
}
found = true
if s.match[offset][i+1] == to {
if s.match[offset][i] == id && s.match[offset][i+1] == to {
s.match[offset][i] = -1
return to, true
//eindex = i
return
}
}
if found {
// s.match[offset][index] = -1
}
return to, found
}
func (s *store) ensureOffset(offset int) {
@ -131,15 +125,29 @@ func (s *store) ensureOffset(offset int) {
}
func (s *store) setMatch(offset, id, to int) {
if toe, match, ok := s.getMatch(offset, id); ok && match && toe == to {
s.ensureOffset(offset)
for i := 0; i < len(s.match[offset]); i += 2 {
if s.match[offset][i] != id || s.match[offset][i+1] != to {
continue
}
return
}
s.ensureOffset(offset)
s.match[offset] = append(s.match[offset], id, to)
}
func (s *store) setNoMatch(offset, id int) {
if len(s.match) > offset {
for i := 0; i < len(s.match[offset]); i += 2 {
if s.match[offset][i] != id {
continue
}
return
}
}
if len(s.noMatch) <= offset {
if cap(s.noMatch) > offset {
s.noMatch = s.noMatch[:offset+1]