4
4
"context"
5
5
"fmt"
6
6
"math"
7
+ "math/rand"
7
8
"net/url"
8
9
"strings"
9
10
"time"
@@ -24,7 +25,6 @@ type Conn struct {
24
25
interrupt context.Context
25
26
pending * Stmt
26
27
stmts []* Stmt
27
- timer * time.Timer
28
28
busy func (context.Context , int ) bool
29
29
log func (xErrorCode , string )
30
30
collation func (* Conn , string )
@@ -36,7 +36,8 @@ type Conn struct {
36
36
rollback func ()
37
37
arena arena
38
38
39
- handle uint32
39
+ kickoff time.Time
40
+ handle uint32
40
41
}
41
42
42
43
// Open calls [OpenFlags] with [OPEN_READWRITE], [OPEN_CREATE] and [OPEN_URI].
@@ -389,38 +390,17 @@ func (c *Conn) BusyTimeout(timeout time.Duration) error {
389
390
}
390
391
391
392
func timeoutCallback (ctx context.Context , mod api.Module , count , tmout int32 ) (retry uint32 ) {
393
+ // https://fractaledmind.github.io/2024/04/15/sqlite-on-rails-the-how-and-why-of-optimal-performance/
392
394
if c , ok := ctx .Value (connKey {}).(* Conn ); ok && c .interrupt .Err () == nil {
393
- const delays = "\x01 \x02 \x05 \x0a \x0f \x14 \x19 \x19 \x19 \x32 \x32 \x64 "
394
- const totals = "\x00 \x01 \x03 \x08 \x12 \x21 \x35 \x4e \x67 \x80 \xb2 \xe4 "
395
- const ndelay = int32 (len (delays ) - 1 )
396
-
397
- var delay , prior int32
398
- if count <= ndelay {
399
- delay = int32 (delays [count ])
400
- prior = int32 (totals [count ])
401
- } else {
402
- delay = int32 (delays [ndelay ])
403
- prior = int32 (totals [ndelay ]) + delay * (count - ndelay )
404
- }
405
-
406
- if delay = min (delay , tmout - prior ); delay > 0 {
407
- delay := time .Duration (delay ) * time .Millisecond
408
- if c .interrupt .Done () == nil {
409
- time .Sleep (delay )
410
- return 1
411
- }
412
- if c .timer == nil {
413
- c .timer = time .NewTimer (delay )
414
- } else {
415
- c .timer .Reset (delay )
416
- }
417
- select {
418
- case <- c .interrupt .Done ():
419
- c .timer .Stop ()
420
- case <- c .timer .C :
421
- return 1
422
- }
395
+ switch {
396
+ case count == 0 :
397
+ c .kickoff = time .Now ()
398
+ case time .Since (c .kickoff ) >= time .Duration (tmout )* time .Millisecond :
399
+ return 0
423
400
}
401
+ const sleepIncrement = 4 * 1024 * 1024 - 1 // power of two, ~4ms
402
+ time .Sleep (time .Duration (rand .Int63 () & sleepIncrement ))
403
+ return 1
424
404
}
425
405
return 0
426
406
}
0 commit comments