-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
utils: parse using byteslice in parseDateTime #1113
utils: parse using byteslice in parseDateTime #1113
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please post the result of this benchmark and remove deprecatedParseDateTime
.
We do not keep old implementations only for benchmark.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed 2c6aa27
Co-authored-by: Inada Naoki <[email protected]>
Co-authored-by: Inada Naoki <[email protected]>
Co-authored-by: Inada Naoki <[email protected]>
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 <[email protected]> * Update utils.go Co-authored-by: Inada Naoki <[email protected]> * Update utils.go Co-authored-by: Inada Naoki <[email protected]> * removed deprecatedParseDateTime from test Co-authored-by: Inada Naoki <[email protected]>
* 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 <[email protected]> * Update utils.go Co-authored-by: Inada Naoki <[email protected]> * Update utils.go Co-authored-by: Inada Naoki <[email protected]> * removed deprecatedParseDateTime from test Co-authored-by: Inada Naoki <[email protected]>
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