Remove a few allocs from Run

This commit is contained in:
Adam Scarr 2017-08-13 16:56:12 +10:00
parent f633909141
commit 0dc37ae5bc
6 changed files with 42 additions and 17 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
cpu.out cpu.out
mem.out mem.out
/vendor /vendor
trace.log

26
errors.go Normal file
View File

@ -0,0 +1,26 @@
package goparsify
import "fmt"
// Error represents a parse error. These will often be set, the parser will back up a little and
// find another viable path. In general when combining errors the longest error should be returned.
type Error struct {
pos int
expected string
}
// Pos is the offset into the document the error was found
func (e *Error) Pos() int { return e.pos }
// Error satisfies the golang error interface
func (e *Error) Error() string { return fmt.Sprintf("offset %d: expected %s", e.pos, e.expected) }
// UnparsedInputError is returned by Run when not all of the input was consumed. There may still be a valid result
type UnparsedInputError struct {
remaining string
}
// Error satisfies the golang error interface
func (e UnparsedInputError) Error() string {
return "left unparsed: " + e.remaining
}

View File

@ -1,7 +1,6 @@
package goparsify package goparsify
import ( import (
"errors"
"fmt" "fmt"
"regexp" "regexp"
"strings" "strings"
@ -90,11 +89,11 @@ func Run(parser Parserish, input string, ws ...VoidParser) (result interface{},
ps.AutoWS() ps.AutoWS()
if ps.Error.expected != "" { if ps.Error.expected != "" {
return ret.Result, ps.Error return ret.Result, &ps.Error
} }
if ps.Get() != "" { if ps.Get() != "" {
return ret.Result, errors.New("left unparsed: " + ps.Get()) return ret.Result, UnparsedInputError{ps.Get()}
} }
return ret.Result, nil return ret.Result, nil

View File

@ -5,6 +5,7 @@ import "testing"
func BenchmarkAny(b *testing.B) { func BenchmarkAny(b *testing.B) {
p := Any("hello", "goodbye", "help") p := Any("hello", "goodbye", "help")
b.ResetTimer()
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
_, _ = Run(p, "hello") _, _ = Run(p, "hello")
_, _ = Run(p, "hello world") _, _ = Run(p, "hello world")

12
scripts/benchalloc.sh Normal file
View File

@ -0,0 +1,12 @@
#!/bin/bash
if [ $# != 1 ] ; then
echo Run this in a directory containing benchmarks and pass it the name of a benchmark. It will dump allocations out to trace.log
exit
fi
set -eu
go test -c
GODEBUG=allocfreetrace=1 ./$(basename $(pwd)).test.exe -test.run=none -test.bench=$1 -test.benchmem -test.benchtime=1ns 2> >(sed -n '/benchmark.go:75/,$p' > trace.log)

View File

@ -1,24 +1,10 @@
package goparsify package goparsify
import ( import (
"fmt"
"unicode" "unicode"
"unicode/utf8" "unicode/utf8"
) )
// Error represents a parse error. These will often be set, the parser will back up a little and
// find another viable path. In general when combining errors the longest error should be returned.
type Error struct {
pos int
expected string
}
// Pos is the offset into the document the error was found
func (e Error) Pos() int { return e.pos }
// Error satisfies the golang error interface
func (e Error) Error() string { return fmt.Sprintf("offset %d: expected %s", e.pos, e.expected) }
// State is the current parse state. It is entirely public because parsers are expected to mutate it during the parse. // State is the current parse state. It is entirely public because parsers are expected to mutate it during the parse.
type State struct { type State struct {
// The full input string // The full input string