utils: parse using byteslice in parseDateTime#1113
utils: parse using byteslice in parseDateTime#1113julienschmidt merged 11 commits intogo-sql-driver:masterfrom Code-Hex:fix/parse-byte-time
Conversation
The benchmark results $ go test -benchmem . -bench "^BenchmarkParseByte" goos: darwin goarch: amd64 pkg: github.com/go-sql-driver/mysql BenchmarkParseByteDateTime-4 12023173 104 ns/op 0 B/op 0 allocs/op BenchmarkParseByteDateTimeStringCast-4 3394239 355 ns/op 32 B/op 1 allocs/op
|
Can we just change the argument type of |
|
@methane Thanks for your reply. |
utils_test.go
Outdated
| loc := time.FixedZone("test", 8*60*60) | ||
| b.ResetTimer() | ||
| for i := 0; i < b.N; i++ { | ||
| _, _ = deprecatedParseDateTime(string(bStr), loc) |
There was a problem hiding this comment.
Please post the result of this benchmark and remove deprecatedParseDateTime.
We do not keep old implementations only for benchmark.
Co-authored-by: Inada Naoki <songofacandy@gmail.com>
Co-authored-by: Inada Naoki <songofacandy@gmail.com>
Co-authored-by: Inada Naoki <songofacandy@gmail.com>
|
nice job!!! I just thought that the Here I have a few questions:
Line 121 in 2c6aa27 Line 133 in 2c6aa27 Line 146 in 2c6aa27 |
|
I have same question with chanxuehong about the range of year(month, day). https://play.golang.org/p/HgQkcLCOGMU package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Parse("2006-01-02 15:04:05.999999", "0000-00-00 00:00:00.000000"))
fmt.Println(time.Parse("2006-01-02 15:04:05.999999", "9999-99-99 99:99:99.999999"))
}I think the range checks are not needed, because MySQL returns correct datetime and we don't need to take care of incorrect datetime. |
|
@chanxuehong @shogo82148 thanks for the mention to me.
When I actually measured it, it wasn't much of a difference, so I thought it was good. Code & Resultsconst base = "0000-00-00 00:00:00.000000"
var bbase = []byte(base)
func BenchmarkByteStringEq(b *testing.B) {
for i := 0; i < b.N; i++ {
b := []byte("0000-00-00 00:00:00.000000")
_ = string(b) == base[:len(b)]
}
}
func BenchmarkByteEq(b *testing.B) {
for i := 0; i < b.N; i++ {
b := []byte("0000-00-00 00:00:00.000000")
_ = bytes.Equal(b, bbase[:len(b)])
}
}Result (two times)
Assumptions, I basically believe that we can trust the values that MySQL passes. So I don't think it's really necessary to do a range check here. The reason for checking here is so that https://play.golang.org/p/4iQJgoOGYIQ But in this case, https://play.golang.org/p/wRD2ylQiF_9 Anyway, I think it's okay to leave out year, day, month range confirmation logic. I'll fix it if the maintainer is agree. |
|
As the comment says, the Go compiler optimize this comparison.
https://play.golang.org/p/T9-R0Bdpfzr So it is not safe that users treat the zero value. Anyway, my question doesn't block merging. |
|
Sorry... |
* fixed the way of parsing datetime when byte slice string The benchmark results $ go test -benchmem . -bench "^BenchmarkParseByte" goos: darwin goarch: amd64 pkg: github.com/go-sql-driver/mysql BenchmarkParseByteDateTime-4 12023173 104 ns/op 0 B/op 0 allocs/op BenchmarkParseByteDateTimeStringCast-4 3394239 355 ns/op 32 B/op 1 allocs/op * added line to AUTHORS file * fixed error handling * fixed nanosec digits * added more tests for error * renamed parseByteDateTime to parseDateTime * reverted base null time * Update utils.go Co-authored-by: Inada Naoki <songofacandy@gmail.com> * Update utils.go Co-authored-by: Inada Naoki <songofacandy@gmail.com> * Update utils.go Co-authored-by: Inada Naoki <songofacandy@gmail.com> * removed deprecatedParseDateTime from test Co-authored-by: Inada Naoki <songofacandy@gmail.com>
* fixed the way of parsing datetime when byte slice string The benchmark results $ go test -benchmem . -bench "^BenchmarkParseByte" goos: darwin goarch: amd64 pkg: github.com/go-sql-driver/mysql BenchmarkParseByteDateTime-4 12023173 104 ns/op 0 B/op 0 allocs/op BenchmarkParseByteDateTimeStringCast-4 3394239 355 ns/op 32 B/op 1 allocs/op * added line to AUTHORS file * fixed error handling * fixed nanosec digits * added more tests for error * renamed parseByteDateTime to parseDateTime * reverted base null time * Update utils.go Co-authored-by: Inada Naoki <songofacandy@gmail.com> * Update utils.go Co-authored-by: Inada Naoki <songofacandy@gmail.com> * Update utils.go Co-authored-by: Inada Naoki <songofacandy@gmail.com> * removed deprecatedParseDateTime from test Co-authored-by: Inada Naoki <songofacandy@gmail.com>
You are right. These checks caused regression: #1252. |
Description
When the time information is passed in byteslice, it takes a long time to parse it. The order in which the current parsing is done is
dest[i]to bytesliceAnd since the format for returning the time information to the client has been decided, I think it's obviously faster to do the parsing ownself right away.
The benchmark results
Code
MySQL datetime format
https://dev.mysql.com/doc/refman/8.0/en/datetime.html
Checklist