Make the parsing even faster 100K RR/s
This commit is contained in:
parent
ea57a49d94
commit
aed704524c
|
@ -19,7 +19,7 @@ Features:
|
||||||
* RFC 1035 zone file parsing;
|
* RFC 1035 zone file parsing;
|
||||||
* Fast:
|
* Fast:
|
||||||
* reply speed around 35/40K qps (Faster hardware -> more qps);
|
* reply speed around 35/40K qps (Faster hardware -> more qps);
|
||||||
* Parsing RRs (zone files) with 80/90K RR/s, that's 5M records in about 58 seconds;
|
* Parsing RRs (zone files) with 95/100K RR/s, that's 5M records in about 50 seconds;
|
||||||
* This is expected to be optimized further.
|
* This is expected to be optimized further.
|
||||||
* Client and server side programming (mimicking the net/http package);
|
* Client and server side programming (mimicking the net/http package);
|
||||||
* Asynchronous queries/replies for client and server;
|
* Asynchronous queries/replies for client and server;
|
||||||
|
|
101
zscan.go
101
zscan.go
|
@ -81,6 +81,7 @@ type lex struct {
|
||||||
value uint8 // Value: _STRING, _BLANK, etc.
|
value uint8 // Value: _STRING, _BLANK, etc.
|
||||||
line int // Line in the file
|
line int // Line in the file
|
||||||
column int // Column in the fil
|
column int // Column in the fil
|
||||||
|
torc uint16 // Type or class as parsed in the lexer, we only need to look this up in the grammar
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tokens are returned when a zone file is parsed.
|
// Tokens are returned when a zone file is parsed.
|
||||||
|
@ -154,7 +155,6 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) {
|
||||||
}
|
}
|
||||||
st := _EXPECT_OWNER_DIR // initial state
|
st := _EXPECT_OWNER_DIR // initial state
|
||||||
var h RR_Header
|
var h RR_Header
|
||||||
var ok bool
|
|
||||||
var defttl uint32 = DefaultTtl
|
var defttl uint32 = DefaultTtl
|
||||||
var prevName string
|
var prevName string
|
||||||
for l := range c {
|
for l := range c {
|
||||||
|
@ -201,28 +201,16 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) {
|
||||||
st = _EXPECT_DIRINCLUDE_BL
|
st = _EXPECT_DIRINCLUDE_BL
|
||||||
case _RRTYPE: // Everthing has been omitted, this is the first thing on the line
|
case _RRTYPE: // Everthing has been omitted, this is the first thing on the line
|
||||||
h.Name = prevName
|
h.Name = prevName
|
||||||
h.Rrtype, ok = Str_rr[strings.ToUpper(l.token)]
|
h.Rrtype = l.torc
|
||||||
if !ok {
|
|
||||||
if h.Rrtype, ok = typeToInt(l.token); !ok {
|
|
||||||
t <- Token{Error: &ParseError{f, "unknown RR type", l}}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st = _EXPECT_RDATA
|
st = _EXPECT_RDATA
|
||||||
case _CLASS: // First thing on the line is the class
|
case _CLASS: // First thing on the line is the class
|
||||||
h.Name = prevName
|
h.Name = prevName
|
||||||
h.Class, ok = Str_class[strings.ToUpper(l.token)]
|
h.Class = l.torc
|
||||||
if !ok {
|
|
||||||
if h.Class, ok = classToInt(l.token); !ok {
|
|
||||||
t <- Token{Error: &ParseError{f, "unknown class", l}}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st = _EXPECT_ANY_NOCLASS_BL
|
st = _EXPECT_ANY_NOCLASS_BL
|
||||||
case _BLANK:
|
case _BLANK:
|
||||||
// Discard, can happen when there is nothing on the
|
// Discard, can happen when there is nothing on the
|
||||||
// line except the RR type
|
// line except the RR type
|
||||||
case _STRING: // First thing on the is the ttl
|
case _STRING: // First thing on the is the ttl
|
||||||
if ttl, ok := stringToTtl(l, f); !ok {
|
if ttl, ok := stringToTtl(l, f); !ok {
|
||||||
t <- Token{Error: &ParseError{f, "not a TTL", l}}
|
t <- Token{Error: &ParseError{f, "not a TTL", l}}
|
||||||
return
|
return
|
||||||
|
@ -317,22 +305,10 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) {
|
||||||
case _EXPECT_ANY:
|
case _EXPECT_ANY:
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case _RRTYPE:
|
case _RRTYPE:
|
||||||
h.Rrtype, ok = Str_rr[strings.ToUpper(l.token)]
|
h.Rrtype = l.torc
|
||||||
if !ok {
|
|
||||||
if h.Rrtype, ok = typeToInt(l.token); !ok {
|
|
||||||
t <- Token{Error: &ParseError{f, "unknown RR type", l}}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st = _EXPECT_RDATA
|
st = _EXPECT_RDATA
|
||||||
case _CLASS:
|
case _CLASS:
|
||||||
h.Class, ok = Str_class[strings.ToUpper(l.token)]
|
h.Class = l.torc
|
||||||
if !ok {
|
|
||||||
if h.Class, ok = classToInt(l.token); !ok {
|
|
||||||
t <- Token{Error: &ParseError{f, "unknown class", l}}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st = _EXPECT_ANY_NOCLASS_BL
|
st = _EXPECT_ANY_NOCLASS_BL
|
||||||
case _STRING: // TTL is this case
|
case _STRING: // TTL is this case
|
||||||
if ttl, ok := stringToTtl(l, f); !ok {
|
if ttl, ok := stringToTtl(l, f); !ok {
|
||||||
|
@ -362,22 +338,10 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) {
|
||||||
case _EXPECT_ANY_NOTTL:
|
case _EXPECT_ANY_NOTTL:
|
||||||
switch l.value {
|
switch l.value {
|
||||||
case _CLASS:
|
case _CLASS:
|
||||||
h.Class, ok = Str_class[strings.ToUpper(l.token)]
|
h.Class = l.torc
|
||||||
if !ok {
|
|
||||||
if h.Class, ok = classToInt(l.token); !ok {
|
|
||||||
t <- Token{Error: &ParseError{f, "unknown class", l}}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st = _EXPECT_RRTYPE_BL
|
st = _EXPECT_RRTYPE_BL
|
||||||
case _RRTYPE:
|
case _RRTYPE:
|
||||||
h.Rrtype, ok = Str_rr[strings.ToUpper(l.token)]
|
h.Rrtype = l.torc
|
||||||
if !ok {
|
|
||||||
if h.Rrtype, ok = typeToInt(l.token); !ok {
|
|
||||||
t <- Token{Error: &ParseError{f, "unknown RR type", l}}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st = _EXPECT_RDATA
|
st = _EXPECT_RDATA
|
||||||
}
|
}
|
||||||
case _EXPECT_ANY_NOCLASS:
|
case _EXPECT_ANY_NOCLASS:
|
||||||
|
@ -392,13 +356,7 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) {
|
||||||
}
|
}
|
||||||
st = _EXPECT_RRTYPE_BL
|
st = _EXPECT_RRTYPE_BL
|
||||||
case _RRTYPE:
|
case _RRTYPE:
|
||||||
h.Rrtype, ok = Str_rr[strings.ToUpper(l.token)]
|
h.Rrtype = l.torc
|
||||||
if !ok {
|
|
||||||
if h.Rrtype, ok = typeToInt(l.token); !ok {
|
|
||||||
t <- Token{Error: &ParseError{f, "unknown RR type", l}}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st = _EXPECT_RDATA
|
st = _EXPECT_RDATA
|
||||||
default:
|
default:
|
||||||
t <- Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}}
|
t <- Token{Error: &ParseError{f, "expecting RR type or TTL, not this...", l}}
|
||||||
|
@ -415,13 +373,7 @@ func parseZone(r io.Reader, origin, f string, t chan Token, include int) {
|
||||||
t <- Token{Error: &ParseError{f, "unknown RR type", l}}
|
t <- Token{Error: &ParseError{f, "unknown RR type", l}}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.Rrtype, ok = Str_rr[strings.ToUpper(l.token)]
|
h.Rrtype = l.torc
|
||||||
if !ok {
|
|
||||||
if h.Rrtype, ok = typeToInt(l.token); !ok {
|
|
||||||
t <- Token{Error: &ParseError{f, "unknown RR type", l}}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
st = _EXPECT_RDATA
|
st = _EXPECT_RDATA
|
||||||
case _EXPECT_RDATA:
|
case _EXPECT_RDATA:
|
||||||
// I could save my token here...? l
|
// I could save my token here...? l
|
||||||
|
@ -524,20 +476,37 @@ func zlexer(s *scan, c chan lex) {
|
||||||
l.token = string(str[:stri])
|
l.token = string(str[:stri])
|
||||||
|
|
||||||
if !rrtype {
|
if !rrtype {
|
||||||
if _, ok := Str_rr[strings.ToUpper(l.token)]; ok {
|
if t, ok := Str_rr[strings.ToUpper(l.token)]; ok {
|
||||||
l.value = _RRTYPE
|
l.value = _RRTYPE
|
||||||
|
l.torc = t
|
||||||
rrtype = true
|
rrtype = true
|
||||||
} else {
|
} else {
|
||||||
if strings.HasPrefix(strings.ToUpper(l.token), "TYPE") {
|
if strings.HasPrefix("TYPE", l.token) {
|
||||||
l.value = _RRTYPE
|
if t, ok := typeToInt(l.token); !ok {
|
||||||
rrtype = true
|
l.token = "unknown RR type"
|
||||||
|
l.err = true
|
||||||
|
c <- l
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
l.value = _RRTYPE
|
||||||
|
l.torc = t
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _, ok := Str_class[strings.ToUpper(l.token)]; ok {
|
if t, ok := Str_class[strings.ToUpper(l.token)]; ok {
|
||||||
l.value = _CLASS
|
l.value = _CLASS
|
||||||
|
l.torc = t
|
||||||
} else {
|
} else {
|
||||||
if strings.HasPrefix(strings.ToUpper(l.token), "CLASS") {
|
if strings.HasPrefix("CLASS", l.token) {
|
||||||
l.value = _CLASS
|
if t, ok := classToInt(l.token); !ok {
|
||||||
|
l.token = "unknown class"
|
||||||
|
l.err = true
|
||||||
|
c <- l
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
l.value = _CLASS
|
||||||
|
l.torc = t
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue