mirror of
https://github.com/golang/go
synced 2024-11-22 00:54:43 -07:00
go/scanner: faster scanning
Optimize some common cases. benchmark old ns/op new ns/op delta BenchmarkScanFile 718907 667960 -7.09% benchmark old MB/s new MB/s speedup BenchmarkScanFile 23.03 25.51 1.11x R=r CC=golang-dev https://golang.org/cl/6454150
This commit is contained in:
parent
7fa3b9f7ea
commit
3df0545a8b
@ -572,14 +572,25 @@ scanAgain:
|
|||||||
// determine token value
|
// determine token value
|
||||||
insertSemi := false
|
insertSemi := false
|
||||||
switch ch := s.ch; {
|
switch ch := s.ch; {
|
||||||
case isLetter(ch):
|
case 'a' <= ch && ch <= 'z':
|
||||||
|
// literals start with a lower-case letter
|
||||||
lit = s.scanIdentifier()
|
lit = s.scanIdentifier()
|
||||||
tok = token.Lookup(lit)
|
if len(lit) > 1 {
|
||||||
switch tok {
|
// keywords are longer than one letter - avoid lookup otherwise
|
||||||
case token.IDENT, token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN:
|
tok = token.Lookup(lit)
|
||||||
|
switch tok {
|
||||||
|
case token.IDENT, token.BREAK, token.CONTINUE, token.FALLTHROUGH, token.RETURN:
|
||||||
|
insertSemi = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
insertSemi = true
|
insertSemi = true
|
||||||
|
tok = token.IDENT
|
||||||
}
|
}
|
||||||
case digitVal(ch) < 10:
|
case 'A' <= ch && ch <= 'Z' || ch == '_':
|
||||||
|
insertSemi = true
|
||||||
|
tok = token.IDENT
|
||||||
|
lit = s.scanIdentifier()
|
||||||
|
case '0' <= ch && ch <= '9':
|
||||||
insertSemi = true
|
insertSemi = true
|
||||||
tok, lit = s.scanNumber(false)
|
tok, lit = s.scanNumber(false)
|
||||||
default:
|
default:
|
||||||
@ -612,7 +623,7 @@ scanAgain:
|
|||||||
case ':':
|
case ':':
|
||||||
tok = s.switch2(token.COLON, token.DEFINE)
|
tok = s.switch2(token.COLON, token.DEFINE)
|
||||||
case '.':
|
case '.':
|
||||||
if digitVal(s.ch) < 10 {
|
if '0' <= s.ch && s.ch <= '9' {
|
||||||
insertSemi = true
|
insertSemi = true
|
||||||
tok, lit = s.scanNumber(true)
|
tok, lit = s.scanNumber(true)
|
||||||
} else if s.ch == '.' {
|
} else if s.ch == '.' {
|
||||||
@ -704,10 +715,17 @@ scanAgain:
|
|||||||
case '|':
|
case '|':
|
||||||
tok = s.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR)
|
tok = s.switch3(token.OR, token.OR_ASSIGN, '|', token.LOR)
|
||||||
default:
|
default:
|
||||||
s.error(s.file.Offset(pos), fmt.Sprintf("illegal character %#U", ch))
|
if isLetter(ch) {
|
||||||
insertSemi = s.insertSemi // preserve insertSemi info
|
// handle any letters we might have missed
|
||||||
tok = token.ILLEGAL
|
insertSemi = true
|
||||||
lit = string(ch)
|
tok = token.IDENT
|
||||||
|
s.scanIdentifier()
|
||||||
|
} else {
|
||||||
|
s.error(s.file.Offset(pos), fmt.Sprintf("illegal character %#U", ch))
|
||||||
|
insertSemi = s.insertSemi // preserve insertSemi info
|
||||||
|
tok = token.ILLEGAL
|
||||||
|
lit = string(ch)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if s.mode&dontInsertSemis == 0 {
|
if s.mode&dontInsertSemis == 0 {
|
||||||
|
@ -6,6 +6,7 @@ package scanner
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@ -705,7 +706,7 @@ func BenchmarkScan(b *testing.B) {
|
|||||||
file := fset.AddFile("", fset.Base(), len(source))
|
file := fset.AddFile("", fset.Base(), len(source))
|
||||||
var s Scanner
|
var s Scanner
|
||||||
b.StartTimer()
|
b.StartTimer()
|
||||||
for i := b.N - 1; i >= 0; i-- {
|
for i := 0; i < b.N; i++ {
|
||||||
s.Init(file, source, nil, ScanComments)
|
s.Init(file, source, nil, ScanComments)
|
||||||
for {
|
for {
|
||||||
_, tok, _ := s.Scan()
|
_, tok, _ := s.Scan()
|
||||||
@ -715,3 +716,26 @@ func BenchmarkScan(b *testing.B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkScanFile(b *testing.B) {
|
||||||
|
b.StopTimer()
|
||||||
|
const filename = "scanner.go"
|
||||||
|
src, err := ioutil.ReadFile(filename)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
file := fset.AddFile(filename, fset.Base(), len(src))
|
||||||
|
b.SetBytes(int64(len(src)))
|
||||||
|
var s Scanner
|
||||||
|
b.StartTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
s.Init(file, src, nil, ScanComments)
|
||||||
|
for {
|
||||||
|
_, tok, _ := s.Scan()
|
||||||
|
if tok == token.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user