use id based cache

This commit is contained in:
Arpad Ryszka 2017-07-15 23:00:43 +02:00
parent 50592ed83f
commit baa2ceede8
5 changed files with 53 additions and 61 deletions

View File

@ -28,7 +28,7 @@ func newChar(
func (p *charParser) nodeName() string { return p.name } func (p *charParser) nodeName() string { return p.name }
func (p *charParser) nodeID() int { return p.id } func (p *charParser) nodeID() int { return p.id }
func (p *charParser) setID(id int) { p.id = p.id } func (p *charParser) setID(id int) { p.id = id }
func (p *charParser) parser(r *registry, parsers *idSet) (parser, error) { func (p *charParser) parser(r *registry, parsers *idSet) (parser, error) {
if parsers.has(p.id) { if parsers.has(p.id) {
@ -85,7 +85,7 @@ func (p *charParser) parse(t Trace, c *context) {
return return
} }
if _, ok := c.fromStore(p.name); ok { if _, ok := c.fromStore(p.id); ok {
// t.Out1("found in store, match:", m) // t.Out1("found in store, match:", m)
return return
} }
@ -93,7 +93,7 @@ func (p *charParser) parse(t Trace, c *context) {
if tok, ok := c.token(); ok && p.match(tok) { if tok, ok := c.token(); ok && p.match(tok) {
// t.Out1("success", string(tok)) // t.Out1("success", string(tok))
n := newNode(p.name, p.id, c.offset, c.offset+1, p.commit) n := newNode(p.name, p.id, c.offset, c.offset+1, p.commit)
c.store.set(c.offset, p.name, n) c.store.set(c.offset, p.id, n)
for _, includedBy := range p.includedBy { for _, includedBy := range p.includedBy {
includedBy.storeIncluded(c, n) includedBy.storeIncluded(c, n)
} }
@ -102,7 +102,7 @@ func (p *charParser) parse(t Trace, c *context) {
return return
} else { } else {
// t.Out1("fail", string(tok)) // t.Out1("fail", string(tok))
c.store.set(c.offset, p.name, nil) c.store.set(c.offset, p.id, nil)
c.fail(c.offset) c.fail(c.offset)
return return
} }

View File

@ -92,7 +92,7 @@ func (p *choiceParser) storeIncluded(c *context, n *Node) {
nc := newNode(p.name, p.id, n.From, n.To, p.commit) nc := newNode(p.name, p.id, n.From, n.To, p.commit)
nc.append(n) nc.append(n)
c.store.set(nc.From, p.name, nc) c.store.set(nc.From, p.id, nc)
for _, includedBy := range p.includedBy { for _, includedBy := range p.includedBy {
includedBy.storeIncluded(c, nc) includedBy.storeIncluded(c, nc)
@ -109,7 +109,7 @@ func (p *choiceParser) parse(t Trace, c *context) {
return return
} }
if _, ok := c.fromStore(p.name); ok { if _, ok := c.fromStore(p.id); ok {
// t.Out1("found in store, match:", m) // t.Out1("found in store, match:", m)
return return
} }
@ -144,7 +144,7 @@ func (p *choiceParser) parse(t Trace, c *context) {
node = newNode(p.name, p.id, c.offset, c.offset, p.commit) node = newNode(p.name, p.id, c.offset, c.offset, p.commit)
node.append(c.node) node.append(c.node)
c.store.set(node.From, p.name, node) c.store.set(node.From, p.id, node)
for _, includedBy := range p.includedBy { for _, includedBy := range p.includedBy {
includedBy.storeIncluded(c, node) includedBy.storeIncluded(c, node)
} }
@ -163,7 +163,7 @@ func (p *choiceParser) parse(t Trace, c *context) {
} }
// t.Out1("fail") // t.Out1("fail")
c.store.set(node.From, p.name, nil) c.store.set(node.From, p.id, nil)
c.fail(node.From) c.fail(node.From)
c.include(initialOffset, p.id) // TODO: test if can be optimized c.include(initialOffset, p.id) // TODO: test if can be optimized
} }

View File

@ -104,8 +104,8 @@ func (c *context) include(offset int, id int) {
c.isExcluded[offset].unset(id) c.isExcluded[offset].unset(id)
} }
func (c *context) fromStore(name string) (bool, bool) { func (c *context) fromStore(id int) (bool, bool) {
n, m, ok := c.store.get(c.offset, name) n, m, ok := c.store.get(c.offset, id)
if !ok { if !ok {
return false, false return false, false
} }

View File

@ -113,7 +113,7 @@ func (p *sequenceParser) storeIncluded(c *context, n *Node) {
nc := newNode(p.name, p.id, n.From, n.To, p.commit) nc := newNode(p.name, p.id, n.From, n.To, p.commit)
nc.append(n) nc.append(n)
c.store.set(nc.From, p.name, nc) c.store.set(nc.From, p.id, nc)
for _, includedBy := range p.includedBy { for _, includedBy := range p.includedBy {
includedBy.storeIncluded(c, nc) includedBy.storeIncluded(c, nc)
@ -145,7 +145,7 @@ func (p *sequenceParser) parse(t Trace, c *context) {
node := newNode(p.name, p.id, c.offset, c.offset, p.commit) node := newNode(p.name, p.id, c.offset, c.offset, p.commit)
for len(items) > 0 { for len(items) > 0 {
m, ok := c.fromStore(items[0].nodeName()) m, ok := c.fromStore(items[0].nodeID())
if ok { if ok {
// t.Out1("sequence item found in store, match:", m, items[0].nodeName(), c.offset) // t.Out1("sequence item found in store, match:", m, items[0].nodeName(), c.offset)
} else { } else {
@ -156,7 +156,7 @@ func (p *sequenceParser) parse(t Trace, c *context) {
if !m { if !m {
if currentCount < ranges[0][0] { if currentCount < ranges[0][0] {
// t.Out1("fail, item failed") // t.Out1("fail, item failed")
c.store.set(node.From, p.name, nil) c.store.set(node.From, p.id, nil)
c.fail(node.From) c.fail(node.From)
c.include(initialOffset, p.id) c.include(initialOffset, p.id)
return return
@ -182,7 +182,7 @@ func (p *sequenceParser) parse(t Trace, c *context) {
// t.Out1("success, items parsed") // t.Out1("success, items parsed")
c.store.set(node.From, p.name, node) c.store.set(node.From, p.id, node)
for _, includedBy := range p.includedBy { for _, includedBy := range p.includedBy {
includedBy.storeIncluded(c, node) includedBy.storeIncluded(c, node)
} }

View File

@ -1,91 +1,83 @@
package treerack package treerack
type storedItem struct {
name string
node *Node
}
type storeEntry struct { type storeEntry struct {
match []*storedItem match *idSet
noMatch []string noMatch *idSet
nodes []*Node
} }
type store struct { type store struct {
tokens []*storeEntry entries []*storeEntry
} }
func (c *store) get(offset int, name string) (*Node, bool, bool) { func (c *store) get(offset int, id int) (*Node, bool, bool) {
if len(c.tokens) <= offset { if len(c.entries) <= offset {
return nil, false, false return nil, false, false
} }
tc := c.tokens[offset] tc := c.entries[offset]
if tc == nil { if tc == nil {
return nil, false, false return nil, false, false
} }
for _, i := range tc.noMatch { if tc.noMatch.has(id) {
if i == name { return nil, false, true
return nil, false, true
}
} }
for _, i := range tc.match { if !tc.match.has(id) {
if i.name == name { return nil, false, false
return i.node, true, true }
for _, n := range tc.nodes {
if n.id == id {
return n, true, true
} }
} }
return nil, false, false return nil, false, false
} }
func (c *store) set(offset int, name string, n *Node) { func (c *store) set(offset int, id int, n *Node) {
var tc *storeEntry var tc *storeEntry
if len(c.tokens) > offset { if len(c.entries) > offset {
tc = c.tokens[offset] tc = c.entries[offset]
} else { } else {
if cap(c.tokens) > offset { if cap(c.entries) > offset {
c.tokens = c.tokens[:offset+1] c.entries = c.entries[:offset+1]
} else { } else {
c.tokens = c.tokens[:cap(c.tokens)] c.entries = c.entries[:cap(c.entries)]
for len(c.tokens) <= offset { for len(c.entries) <= offset {
c.tokens = append(c.tokens, nil) c.entries = append(c.entries, nil)
} }
} }
tc = &storeEntry{} tc = &storeEntry{
c.tokens[offset] = tc match: &idSet{},
noMatch: &idSet{},
}
c.entries[offset] = tc
} }
if n == nil { if n == nil {
for _, i := range tc.match { if tc.match.has(id) {
if i.name == name { return
return
}
} }
for _, i := range tc.noMatch { tc.noMatch.set(id)
if i == name {
return
}
}
tc.noMatch = append(tc.noMatch, name)
return return
} }
for _, i := range tc.match { tc.match.set(id)
if i.name == name { for i, ni := range tc.nodes {
if n.tokenLength() > i.node.tokenLength() { if ni.id == id {
i.node = n if n.tokenLength() > ni.tokenLength() {
tc.nodes[i] = n
} }
return return
} }
} }
tc.match = append(tc.match, &storedItem{ tc.nodes = append(tc.nodes, n)
name: name,
node: n,
})
} }