Skip to content
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

use syscall.Gettimeofday to get current time #961

Merged
merged 7 commits into from
Jan 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions canal/canal.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/go-mysql-org/go-mysql/mysql"
"github.com/go-mysql-org/go-mysql/replication"
"github.com/go-mysql-org/go-mysql/schema"
"github.com/go-mysql-org/go-mysql/utils"
"github.com/pingcap/errors"
"github.com/pingcap/tidb/pkg/parser"
"github.com/siddontang/go-log/log"
Expand Down Expand Up @@ -231,7 +232,7 @@ func (c *Canal) run() error {
c.cancel()
}()

c.master.UpdateTimestamp(uint32(time.Now().Unix()))
c.master.UpdateTimestamp(uint32(utils.Now().Unix()))

if !c.dumped {
c.dumped = true
Expand Down Expand Up @@ -373,7 +374,7 @@ func (c *Canal) GetTable(db string, table string) (*schema.Table, error) {
// if DiscardNoMetaRowEvent is true, we just log this error
if c.cfg.DiscardNoMetaRowEvent {
c.tableLock.Lock()
c.errorTablesGetTime[key] = time.Now()
c.errorTablesGetTime[key] = utils.Now()
c.tableLock.Unlock()
// log error and return ErrMissingTableMeta
c.cfg.Logger.Errorf("canal get table meta err: %v", errors.Trace(err))
Expand Down
3 changes: 2 additions & 1 deletion canal/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (

"github.com/go-mysql-org/go-mysql/client"
"github.com/go-mysql-org/go-mysql/mysql"
"github.com/go-mysql-org/go-mysql/utils"
)

type DumpConfig struct {
Expand Down Expand Up @@ -142,7 +143,7 @@ func NewDefaultConfig() *Config {
c.User = mysql.DEFAULT_USER
c.Password = mysql.DEFAULT_PASSWORD
c.Charset = mysql.DEFAULT_CHARSET
c.ServerID = uint32(rand.New(rand.NewSource(time.Now().Unix())).Intn(1000)) + 1001
c.ServerID = uint32(rand.New(rand.NewSource(utils.Now().Unix())).Intn(1000)) + 1001
c.Flavor = mysql.DEFAULT_FLAVOR

c.Dump.ExecutionPath = mysql.DEFAULT_DUMP_EXECUTION_PATH
Expand Down
5 changes: 3 additions & 2 deletions canal/dump.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

"github.com/go-mysql-org/go-mysql/mysql"
"github.com/go-mysql-org/go-mysql/schema"
"github.com/go-mysql-org/go-mysql/utils"
"github.com/pingcap/errors"
"github.com/shopspring/decimal"
)
Expand Down Expand Up @@ -142,7 +143,7 @@ func (c *Canal) dump() error {
return errors.New("mysqldump does not exist")
}

c.master.UpdateTimestamp(uint32(time.Now().Unix()))
c.master.UpdateTimestamp(uint32(utils.Now().Unix()))

h := &dumpParseHandler{c: c}
// If users call StartFromGTID with empty position to start dumping with gtid,
Expand All @@ -167,7 +168,7 @@ func (c *Canal) dump() error {
h.pos = uint64(pos.Pos)
}

start := time.Now()
start := utils.Now()
c.cfg.Logger.Info("try dump MySQL and parse")
if err := c.dumper.DumpAndParse(h); err != nil {
return errors.Trace(err)
Expand Down
3 changes: 2 additions & 1 deletion canal/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/go-mysql-org/go-mysql/mysql"
"github.com/go-mysql-org/go-mysql/replication"
"github.com/go-mysql-org/go-mysql/schema"
"github.com/go-mysql-org/go-mysql/utils"
"github.com/pingcap/errors"
"github.com/pingcap/tidb/pkg/parser/ast"
)
Expand Down Expand Up @@ -253,7 +254,7 @@ func (c *Canal) updateTable(header *replication.EventHeader, db, table string) (
}
func (c *Canal) updateReplicationDelay(ev *replication.BinlogEvent) {
var newDelay uint32
now := uint32(time.Now().Unix())
now := uint32(utils.Now().Unix())
if now >= ev.Header.Timestamp {
newDelay = now - ev.Header.Timestamp
}
Expand Down
5 changes: 3 additions & 2 deletions client/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"sync"
"time"

"github.com/go-mysql-org/go-mysql/utils"
"github.com/pingcap/errors"
)

Expand Down Expand Up @@ -247,7 +248,7 @@ func (pool *Pool) putConnection(connection Connection) {
}

func (pool *Pool) nowTs() Timestamp {
return Timestamp(time.Now().Unix())
return Timestamp(utils.Now().Unix())
}

func (pool *Pool) getConnection(ctx context.Context) (Connection, error) {
Expand Down Expand Up @@ -553,7 +554,7 @@ func (pool *Pool) startNewConnections(count int) {
}

func (pool *Pool) ping(conn *Conn) error {
deadline := time.Now().Add(100 * time.Millisecond)
deadline := utils.Now().Add(100 * time.Millisecond)
_ = conn.SetDeadline(deadline)
err := conn.Ping()
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions packet/conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func (c *Conn) ReadPacketReuseMem(dst []byte) ([]byte, error) {
// newCompressedPacketReader creates a new compressed packet reader.
func (c *Conn) newCompressedPacketReader() (io.Reader, error) {
if c.readTimeout != 0 {
if err := c.SetReadDeadline(time.Now().Add(c.readTimeout)); err != nil {
if err := c.SetReadDeadline(utils.Now().Add(c.readTimeout)); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -200,7 +200,7 @@ func (c *Conn) copyN(dst io.Writer, n int64) (int64, error) {
// Call ReadAtLeast with the currentPacketReader as it may change on every iteration
// of this loop.
if c.readTimeout != 0 {
if err := c.SetReadDeadline(time.Now().Add(c.readTimeout)); err != nil {
if err := c.SetReadDeadline(utils.Now().Add(c.readTimeout)); err != nil {
return written, err
}
}
Expand Down Expand Up @@ -344,7 +344,7 @@ func (c *Conn) WritePacket(data []byte) error {

func (c *Conn) writeWithTimeout(b []byte) (n int, err error) {
if c.writeTimeout != 0 {
if err := c.SetWriteDeadline(time.Now().Add(c.writeTimeout)); err != nil {
if err := c.SetWriteDeadline(utils.Now().Add(c.writeTimeout)); err != nil {
return n, err
}
}
Expand Down
7 changes: 4 additions & 3 deletions replication/binlogsyncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (

"github.com/go-mysql-org/go-mysql/client"
. "github.com/go-mysql-org/go-mysql/mysql"
"github.com/go-mysql-org/go-mysql/utils"
)

var (
Expand Down Expand Up @@ -227,7 +228,7 @@ func (b *BinlogSyncer) close() {
b.cancel()

if b.c != nil {
err := b.c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
err := b.c.SetReadDeadline(utils.Now().Add(100 * time.Millisecond))
if err != nil {
b.cfg.Logger.Warnf(`could not set read deadline: %s`, err)
}
Expand Down Expand Up @@ -288,7 +289,7 @@ func (b *BinlogSyncer) registerSlave() error {

//set read timeout
if b.cfg.ReadTimeout > 0 {
_ = b.c.SetReadDeadline(time.Now().Add(b.cfg.ReadTimeout))
_ = b.c.SetReadDeadline(utils.Now().Add(b.cfg.ReadTimeout))
}

if b.cfg.RecvBufferSize > 0 {
Expand Down Expand Up @@ -791,7 +792,7 @@ func (b *BinlogSyncer) onStream(s *BinlogStreamer) {

//set read timeout
if b.cfg.ReadTimeout > 0 {
_ = b.c.SetReadDeadline(time.Now().Add(b.cfg.ReadTimeout))
_ = b.c.SetReadDeadline(utils.Now().Add(b.cfg.ReadTimeout))
}

// Reset retry count on successful packet receieve
Expand Down
3 changes: 2 additions & 1 deletion replication/replication_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/go-mysql-org/go-mysql/client"
"github.com/go-mysql-org/go-mysql/mysql"
"github.com/go-mysql-org/go-mysql/test_util"
"github.com/go-mysql-org/go-mysql/utils"
)

var testOutputLogs = flag.Bool("out", false, "output binlog event")
Expand Down Expand Up @@ -335,7 +336,7 @@ func (t *testSyncerSuite) testPositionSync() {

// Test re-sync.
time.Sleep(100 * time.Millisecond)
_ = t.b.c.SetReadDeadline(time.Now().Add(time.Millisecond))
_ = t.b.c.SetReadDeadline(utils.Now().Add(time.Millisecond))
time.Sleep(100 * time.Millisecond)

t.testSync(s)
Expand Down
9 changes: 5 additions & 4 deletions server/caching_sha2_cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/go-mysql-org/go-mysql/mysql"
"github.com/go-mysql-org/go-mysql/test_util"
"github.com/go-mysql-org/go-mysql/test_util/test_keys"
"github.com/go-mysql-org/go-mysql/utils"
)

var delay = 50
Expand Down Expand Up @@ -131,13 +132,13 @@ func (s *cacheTestSuite) runSelect() {

func (s *cacheTestSuite) TestCache() {
// first connection
t1 := time.Now()
t1 := utils.Now()
var err error
s.db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=%s", *testUser, *testPassword, s.serverAddr, *testDB, s.tlsPara))
require.NoError(s.T(), err)
s.db.SetMaxIdleConns(4)
s.runSelect()
t2 := time.Now()
t2 := utils.Now()

d1 := int(t2.Sub(t1).Nanoseconds() / 1e6)
//log.Debugf("first connection took %d milliseconds", d1)
Expand All @@ -149,12 +150,12 @@ func (s *cacheTestSuite) TestCache() {
}

// second connection
t3 := time.Now()
t3 := utils.Now()
s.db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=%s", *testUser, *testPassword, s.serverAddr, *testDB, s.tlsPara))
require.NoError(s.T(), err)
s.db.SetMaxIdleConns(4)
s.runSelect()
t4 := time.Now()
t4 := utils.Now()

d2 := int(t4.Sub(t3).Nanoseconds() / 1e6)
//log.Debugf("second connection took %d milliseconds", d2)
Expand Down
11 changes: 6 additions & 5 deletions server/ssl.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"time"

"github.com/go-mysql-org/go-mysql/utils"
)

// NewServerTLSConfig: generate TLS config for server side
Expand Down Expand Up @@ -75,8 +76,8 @@ func generateAndSignRSACerts(caPem, caKey []byte) ([]byte, []byte) {
StreetAddress: []string{"ADDRESS"},
PostalCode: []string{"POSTAL_CODE"},
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10, 0, 0),
NotBefore: utils.Now(),
NotAfter: utils.Now().AddDate(10, 0, 0),
SubjectKeyId: []byte{1, 2, 3, 4, 6},
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature,
Expand Down Expand Up @@ -112,8 +113,8 @@ func generateCA() ([]byte, []byte) {
StreetAddress: []string{"ADDRESS"},
PostalCode: []string{"POSTAL_CODE"},
},
NotBefore: time.Now(),
NotAfter: time.Now().AddDate(10, 0, 0),
NotBefore: utils.Now(),
NotAfter: utils.Now().AddDate(10, 0, 0),
IsCA: true,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment,
Expand Down
7 changes: 7 additions & 0 deletions utils/now.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
//go:build !unix

package utils

import "time"

var Now = time.Now
19 changes: 19 additions & 0 deletions utils/now_unix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//go:build unix

package utils

import (
"syscall"
"time"
)

// Now is a faster method to get current time
func Now() time.Time {
var tv syscall.Timeval
if err := syscall.Gettimeofday(&tv); err != nil {
// If it failed at syscall, use time package instead
return time.Now()
}

return time.Unix(0, syscall.TimevalToNsec(tv))
}
41 changes: 41 additions & 0 deletions utils/now_unix_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//go:build unix

package utils

import (
"fmt"
"testing"
"time"

"github.com/stretchr/testify/assert"
)

func TestCustomTimeNow(t *testing.T) {
precision := time.Millisecond

for i := 0; i < 1000; i++ {
timestamp := time.Now()
customTimestamp := Now()

// two timestamp should within 1 percistion
assert.WithinDuration(t, timestamp, customTimestamp, precision, fmt.Sprintf("Loop: %d: customTimestamp should within %s. timestamp: %d, customTimestamp: %d", i, precision.String(), timestamp.UnixNano(), customTimestamp.UnixNano()))

time.Sleep(time.Nanosecond)
}
}

func BenchmarkGoTimeNow(t *testing.B) {
t.ResetTimer()
for n := 0; n < t.N; n++ {
_ = time.Now()
}
t.StopTimer()
}

func BenchmarkCustomTimeNow(t *testing.B) {
t.ResetTimer()
for n := 0; n < t.N; n++ {
_ = Now()
}
t.StopTimer()
}
Loading