Skip to content

Commit dc262fe

Browse files
hjweddielance6716
andauthored
use syscall.Gettimeofday to get current time (#961)
* use syscall.Gettimeofday to get current time * use Gettimeofday in just linux and darwin * rename file and add some test case * fix test file syntax * fix within check * fix code problem --------- Co-authored-by: lance6716 <[email protected]>
1 parent a66e74e commit dc262fe

13 files changed

+100
-24
lines changed

canal/canal.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/go-mysql-org/go-mysql/mysql"
1919
"github.com/go-mysql-org/go-mysql/replication"
2020
"github.com/go-mysql-org/go-mysql/schema"
21+
"github.com/go-mysql-org/go-mysql/utils"
2122
"github.com/pingcap/errors"
2223
"github.com/pingcap/tidb/pkg/parser"
2324
"github.com/siddontang/go-log/log"
@@ -231,7 +232,7 @@ func (c *Canal) run() error {
231232
c.cancel()
232233
}()
233234

234-
c.master.UpdateTimestamp(uint32(time.Now().Unix()))
235+
c.master.UpdateTimestamp(uint32(utils.Now().Unix()))
235236

236237
if !c.dumped {
237238
c.dumped = true
@@ -373,7 +374,7 @@ func (c *Canal) GetTable(db string, table string) (*schema.Table, error) {
373374
// if DiscardNoMetaRowEvent is true, we just log this error
374375
if c.cfg.DiscardNoMetaRowEvent {
375376
c.tableLock.Lock()
376-
c.errorTablesGetTime[key] = time.Now()
377+
c.errorTablesGetTime[key] = utils.Now()
377378
c.tableLock.Unlock()
378379
// log error and return ErrMissingTableMeta
379380
c.cfg.Logger.Errorf("canal get table meta err: %v", errors.Trace(err))

canal/config.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414

1515
"github.com/go-mysql-org/go-mysql/client"
1616
"github.com/go-mysql-org/go-mysql/mysql"
17+
"github.com/go-mysql-org/go-mysql/utils"
1718
)
1819

1920
type DumpConfig struct {
@@ -142,7 +143,7 @@ func NewDefaultConfig() *Config {
142143
c.User = mysql.DEFAULT_USER
143144
c.Password = mysql.DEFAULT_PASSWORD
144145
c.Charset = mysql.DEFAULT_CHARSET
145-
c.ServerID = uint32(rand.New(rand.NewSource(time.Now().Unix())).Intn(1000)) + 1001
146+
c.ServerID = uint32(rand.New(rand.NewSource(utils.Now().Unix())).Intn(1000)) + 1001
146147
c.Flavor = mysql.DEFAULT_FLAVOR
147148

148149
c.Dump.ExecutionPath = mysql.DEFAULT_DUMP_EXECUTION_PATH

canal/dump.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/go-mysql-org/go-mysql/mysql"
1111
"github.com/go-mysql-org/go-mysql/schema"
12+
"github.com/go-mysql-org/go-mysql/utils"
1213
"github.com/pingcap/errors"
1314
"github.com/shopspring/decimal"
1415
)
@@ -142,7 +143,7 @@ func (c *Canal) dump() error {
142143
return errors.New("mysqldump does not exist")
143144
}
144145

145-
c.master.UpdateTimestamp(uint32(time.Now().Unix()))
146+
c.master.UpdateTimestamp(uint32(utils.Now().Unix()))
146147

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

170-
start := time.Now()
171+
start := utils.Now()
171172
c.cfg.Logger.Info("try dump MySQL and parse")
172173
if err := c.dumper.DumpAndParse(h); err != nil {
173174
return errors.Trace(err)

canal/sync.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/go-mysql-org/go-mysql/mysql"
88
"github.com/go-mysql-org/go-mysql/replication"
99
"github.com/go-mysql-org/go-mysql/schema"
10+
"github.com/go-mysql-org/go-mysql/utils"
1011
"github.com/pingcap/errors"
1112
"github.com/pingcap/tidb/pkg/parser/ast"
1213
)
@@ -253,7 +254,7 @@ func (c *Canal) updateTable(header *replication.EventHeader, db, table string) (
253254
}
254255
func (c *Canal) updateReplicationDelay(ev *replication.BinlogEvent) {
255256
var newDelay uint32
256-
now := uint32(time.Now().Unix())
257+
now := uint32(utils.Now().Unix())
257258
if now >= ev.Header.Timestamp {
258259
newDelay = now - ev.Header.Timestamp
259260
}

client/pool.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"sync"
99
"time"
1010

11+
"github.com/go-mysql-org/go-mysql/utils"
1112
"github.com/pingcap/errors"
1213
)
1314

@@ -247,7 +248,7 @@ func (pool *Pool) putConnection(connection Connection) {
247248
}
248249

249250
func (pool *Pool) nowTs() Timestamp {
250-
return Timestamp(time.Now().Unix())
251+
return Timestamp(utils.Now().Unix())
251252
}
252253

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

555556
func (pool *Pool) ping(conn *Conn) error {
556-
deadline := time.Now().Add(100 * time.Millisecond)
557+
deadline := utils.Now().Add(100 * time.Millisecond)
557558
_ = conn.SetDeadline(deadline)
558559
err := conn.Ping()
559560
if err != nil {

packet/conn.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ func (c *Conn) ReadPacketReuseMem(dst []byte) ([]byte, error) {
150150
// newCompressedPacketReader creates a new compressed packet reader.
151151
func (c *Conn) newCompressedPacketReader() (io.Reader, error) {
152152
if c.readTimeout != 0 {
153-
if err := c.SetReadDeadline(time.Now().Add(c.readTimeout)); err != nil {
153+
if err := c.SetReadDeadline(utils.Now().Add(c.readTimeout)); err != nil {
154154
return nil, err
155155
}
156156
}
@@ -200,7 +200,7 @@ func (c *Conn) copyN(dst io.Writer, n int64) (int64, error) {
200200
// Call ReadAtLeast with the currentPacketReader as it may change on every iteration
201201
// of this loop.
202202
if c.readTimeout != 0 {
203-
if err := c.SetReadDeadline(time.Now().Add(c.readTimeout)); err != nil {
203+
if err := c.SetReadDeadline(utils.Now().Add(c.readTimeout)); err != nil {
204204
return written, err
205205
}
206206
}
@@ -344,7 +344,7 @@ func (c *Conn) WritePacket(data []byte) error {
344344

345345
func (c *Conn) writeWithTimeout(b []byte) (n int, err error) {
346346
if c.writeTimeout != 0 {
347-
if err := c.SetWriteDeadline(time.Now().Add(c.writeTimeout)); err != nil {
347+
if err := c.SetWriteDeadline(utils.Now().Add(c.writeTimeout)); err != nil {
348348
return n, err
349349
}
350350
}

replication/binlogsyncer.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919

2020
"github.com/go-mysql-org/go-mysql/client"
2121
. "github.com/go-mysql-org/go-mysql/mysql"
22+
"github.com/go-mysql-org/go-mysql/utils"
2223
)
2324

2425
var (
@@ -227,7 +228,7 @@ func (b *BinlogSyncer) close() {
227228
b.cancel()
228229

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

289290
//set read timeout
290291
if b.cfg.ReadTimeout > 0 {
291-
_ = b.c.SetReadDeadline(time.Now().Add(b.cfg.ReadTimeout))
292+
_ = b.c.SetReadDeadline(utils.Now().Add(b.cfg.ReadTimeout))
292293
}
293294

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

792793
//set read timeout
793794
if b.cfg.ReadTimeout > 0 {
794-
_ = b.c.SetReadDeadline(time.Now().Add(b.cfg.ReadTimeout))
795+
_ = b.c.SetReadDeadline(utils.Now().Add(b.cfg.ReadTimeout))
795796
}
796797

797798
// Reset retry count on successful packet receieve

replication/replication_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/go-mysql-org/go-mysql/client"
1818
"github.com/go-mysql-org/go-mysql/mysql"
1919
"github.com/go-mysql-org/go-mysql/test_util"
20+
"github.com/go-mysql-org/go-mysql/utils"
2021
)
2122

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

336337
// Test re-sync.
337338
time.Sleep(100 * time.Millisecond)
338-
_ = t.b.c.SetReadDeadline(time.Now().Add(time.Millisecond))
339+
_ = t.b.c.SetReadDeadline(utils.Now().Add(time.Millisecond))
339340
time.Sleep(100 * time.Millisecond)
340341

341342
t.testSync(s)

server/caching_sha2_cache_test.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/go-mysql-org/go-mysql/mysql"
1919
"github.com/go-mysql-org/go-mysql/test_util"
2020
"github.com/go-mysql-org/go-mysql/test_util/test_keys"
21+
"github.com/go-mysql-org/go-mysql/utils"
2122
)
2223

2324
var delay = 50
@@ -131,13 +132,13 @@ func (s *cacheTestSuite) runSelect() {
131132

132133
func (s *cacheTestSuite) TestCache() {
133134
// first connection
134-
t1 := time.Now()
135+
t1 := utils.Now()
135136
var err error
136137
s.db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=%s", *testUser, *testPassword, s.serverAddr, *testDB, s.tlsPara))
137138
require.NoError(s.T(), err)
138139
s.db.SetMaxIdleConns(4)
139140
s.runSelect()
140-
t2 := time.Now()
141+
t2 := utils.Now()
141142

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

151152
// second connection
152-
t3 := time.Now()
153+
t3 := utils.Now()
153154
s.db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?tls=%s", *testUser, *testPassword, s.serverAddr, *testDB, s.tlsPara))
154155
require.NoError(s.T(), err)
155156
s.db.SetMaxIdleConns(4)
156157
s.runSelect()
157-
t4 := time.Now()
158+
t4 := utils.Now()
158159

159160
d2 := int(t4.Sub(t3).Nanoseconds() / 1e6)
160161
//log.Debugf("second connection took %d milliseconds", d2)

server/ssl.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import (
88
"crypto/x509/pkix"
99
"encoding/pem"
1010
"math/big"
11-
"time"
11+
12+
"github.com/go-mysql-org/go-mysql/utils"
1213
)
1314

1415
// NewServerTLSConfig: generate TLS config for server side
@@ -75,8 +76,8 @@ func generateAndSignRSACerts(caPem, caKey []byte) ([]byte, []byte) {
7576
StreetAddress: []string{"ADDRESS"},
7677
PostalCode: []string{"POSTAL_CODE"},
7778
},
78-
NotBefore: time.Now(),
79-
NotAfter: time.Now().AddDate(10, 0, 0),
79+
NotBefore: utils.Now(),
80+
NotAfter: utils.Now().AddDate(10, 0, 0),
8081
SubjectKeyId: []byte{1, 2, 3, 4, 6},
8182
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
8283
KeyUsage: x509.KeyUsageDigitalSignature,
@@ -112,8 +113,8 @@ func generateCA() ([]byte, []byte) {
112113
StreetAddress: []string{"ADDRESS"},
113114
PostalCode: []string{"POSTAL_CODE"},
114115
},
115-
NotBefore: time.Now(),
116-
NotAfter: time.Now().AddDate(10, 0, 0),
116+
NotBefore: utils.Now(),
117+
NotAfter: utils.Now().AddDate(10, 0, 0),
117118
IsCA: true,
118119
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth},
119120
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign | x509.KeyUsageKeyEncipherment,

utils/now.go

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//go:build !unix
2+
3+
package utils
4+
5+
import "time"
6+
7+
var Now = time.Now

utils/now_unix.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//go:build unix
2+
3+
package utils
4+
5+
import (
6+
"syscall"
7+
"time"
8+
)
9+
10+
// Now is a faster method to get current time
11+
func Now() time.Time {
12+
var tv syscall.Timeval
13+
if err := syscall.Gettimeofday(&tv); err != nil {
14+
// If it failed at syscall, use time package instead
15+
return time.Now()
16+
}
17+
18+
return time.Unix(0, syscall.TimevalToNsec(tv))
19+
}

utils/now_unix_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//go:build unix
2+
3+
package utils
4+
5+
import (
6+
"fmt"
7+
"testing"
8+
"time"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestCustomTimeNow(t *testing.T) {
14+
precision := time.Millisecond
15+
16+
for i := 0; i < 1000; i++ {
17+
timestamp := time.Now()
18+
customTimestamp := Now()
19+
20+
// two timestamp should within 1 percistion
21+
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()))
22+
23+
time.Sleep(time.Nanosecond)
24+
}
25+
}
26+
27+
func BenchmarkGoTimeNow(t *testing.B) {
28+
t.ResetTimer()
29+
for n := 0; n < t.N; n++ {
30+
_ = time.Now()
31+
}
32+
t.StopTimer()
33+
}
34+
35+
func BenchmarkCustomTimeNow(t *testing.B) {
36+
t.ResetTimer()
37+
for n := 0; n < t.N; n++ {
38+
_ = Now()
39+
}
40+
t.StopTimer()
41+
}

0 commit comments

Comments
 (0)