Skip to content

Commit c067e36

Browse files
committed
Improve SetInterrupt performance.
1 parent 35a2dbd commit c067e36

File tree

4 files changed

+36
-32
lines changed

4 files changed

+36
-32
lines changed

blob.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (c *Conn) OpenBlob(db, table, column string, row int64, write bool) (*Blob,
4242
flags = 1
4343
}
4444

45-
c.checkInterrupt(c.handle)
45+
c.checkInterrupt()
4646
rc := res_t(c.call("sqlite3_blob_open", stk_t(c.handle),
4747
stk_t(dbPtr), stk_t(tablePtr), stk_t(columnPtr),
4848
stk_t(row), stk_t(flags), stk_t(blobPtr)))
@@ -253,7 +253,7 @@ func (b *Blob) Seek(offset int64, whence int) (int64, error) {
253253
//
254254
// https://sqlite.org/c3ref/blob_reopen.html
255255
func (b *Blob) Reopen(row int64) error {
256-
b.c.checkInterrupt(b.c.handle)
256+
b.c.checkInterrupt()
257257
err := b.c.error(res_t(b.c.call("sqlite3_blob_reopen", stk_t(b.handle), stk_t(row))))
258258
b.bytes = int64(int32(b.c.call("sqlite3_blob_bytes", stk_t(b.handle))))
259259
b.offset = 0

conn.go

Lines changed: 31 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ type Conn struct {
2525
*sqlite
2626

2727
interrupt context.Context
28-
pending *Stmt
2928
stmts []*Stmt
3029
busy func(context.Context, int) bool
3130
log func(xErrorCode, string)
@@ -41,7 +40,9 @@ type Conn struct {
4140
busylst time.Time
4241
arena arena
4342
handle ptr_t
44-
nprogr uint8
43+
pending ptr_t
44+
stepped bool
45+
gosched uint8
4546
}
4647

4748
// Open calls [OpenFlags] with [OPEN_READWRITE], [OPEN_CREATE] and [OPEN_URI].
@@ -133,7 +134,6 @@ func (c *Conn) openDB(filename string, flags OpenFlag) (ptr_t, error) {
133134
}
134135
}
135136
if pragmas.Len() != 0 {
136-
c.checkInterrupt(handle)
137137
pragmaPtr := c.arena.string(pragmas.String())
138138
rc := res_t(c.call("sqlite3_exec", stk_t(handle), stk_t(pragmaPtr), 0, 0, 0))
139139
if err := c.sqlite.error(rc, handle, pragmas.String()); err != nil {
@@ -167,8 +167,8 @@ func (c *Conn) Close() error {
167167
return nil
168168
}
169169

170-
c.pending.Close()
171-
c.pending = nil
170+
c.call("sqlite3_finalize", stk_t(c.pending))
171+
c.pending = 0
172172

173173
rc := res_t(c.call("sqlite3_close", stk_t(c.handle)))
174174
if err := c.error(rc); err != nil {
@@ -187,7 +187,7 @@ func (c *Conn) Exec(sql string) error {
187187
defer c.arena.mark()()
188188
sqlPtr := c.arena.string(sql)
189189

190-
c.checkInterrupt(c.handle)
190+
c.checkInterrupt()
191191
rc := res_t(c.call("sqlite3_exec", stk_t(c.handle), stk_t(sqlPtr), 0, 0, 0))
192192
return c.error(rc, sql)
193193
}
@@ -211,16 +211,16 @@ func (c *Conn) PrepareFlags(sql string, flags PrepareFlag) (stmt *Stmt, tail str
211211
defer c.arena.mark()()
212212
stmtPtr := c.arena.new(ptrlen)
213213
tailPtr := c.arena.new(ptrlen)
214-
sqlPtr := c.arena.string(sql)
214+
textPtr := c.arena.string(sql)
215215

216-
c.checkInterrupt(c.handle)
216+
c.checkInterrupt()
217217
rc := res_t(c.call("sqlite3_prepare_v3", stk_t(c.handle),
218-
stk_t(sqlPtr), stk_t(len(sql)+1), stk_t(flags),
218+
stk_t(textPtr), stk_t(len(sql)+1), stk_t(flags),
219219
stk_t(stmtPtr), stk_t(tailPtr)))
220220

221-
stmt = &Stmt{c: c}
221+
stmt = &Stmt{c: c, sql: sql}
222222
stmt.handle = util.Read32[ptr_t](c.mod, stmtPtr)
223-
if sql := sql[util.Read32[ptr_t](c.mod, tailPtr)-sqlPtr:]; sql != "" {
223+
if sql := sql[util.Read32[ptr_t](c.mod, tailPtr)-textPtr:]; sql != "" {
224224
tail = sql
225225
}
226226

@@ -344,40 +344,44 @@ func (c *Conn) SetInterrupt(ctx context.Context) (old context.Context) {
344344
old = c.interrupt
345345
c.interrupt = ctx
346346

347-
if ctx == old || ctx.Done() == old.Done() {
347+
if ctx == old {
348348
return old
349349
}
350350

351-
// A busy SQL statement prevents SQLite from ignoring an interrupt
351+
// An active SQL statement prevents SQLite from ignoring an interrupt
352352
// that comes before any other statements are started.
353-
if c.pending == nil {
353+
if c.pending == 0 {
354354
defer c.arena.mark()()
355355
stmtPtr := c.arena.new(ptrlen)
356-
loopPtr := c.arena.string(`WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x FROM c) SELECT x FROM c`)
357-
c.call("sqlite3_prepare_v3", stk_t(c.handle), stk_t(loopPtr), math.MaxUint64,
356+
textPtr := c.arena.string(`SELECT 0 UNION ALL SELECT 0`)
357+
c.call("sqlite3_prepare_v3", stk_t(c.handle), stk_t(textPtr), math.MaxUint64,
358358
stk_t(PREPARE_PERSISTENT), stk_t(stmtPtr), 0)
359-
c.pending = &Stmt{c: c}
360-
c.pending.handle = util.Read32[ptr_t](c.mod, stmtPtr)
359+
c.pending = util.Read32[ptr_t](c.mod, stmtPtr)
361360
}
362361

363-
if old.Done() != nil && ctx.Err() == nil {
364-
c.pending.Reset()
365-
}
366-
if ctx.Done() != nil {
367-
c.pending.Step()
362+
if c.stepped && ctx.Err() == nil {
363+
c.call("sqlite3_reset", stk_t(c.pending))
364+
c.stepped = false
365+
} else {
366+
c.checkInterrupt()
368367
}
369368
return old
370369
}
371370

372-
func (c *Conn) checkInterrupt(handle ptr_t) {
373-
if c.interrupt.Err() != nil {
374-
c.call("sqlite3_interrupt", stk_t(handle))
371+
func (c *Conn) checkInterrupt() {
372+
if c.interrupt.Err() == nil {
373+
return
374+
}
375+
if !c.stepped {
376+
c.call("sqlite3_step", stk_t(c.pending))
377+
c.stepped = true
375378
}
379+
c.call("sqlite3_interrupt", stk_t(c.handle))
376380
}
377381

378382
func progressCallback(ctx context.Context, mod api.Module, _ ptr_t) (interrupt int32) {
379383
if c, ok := ctx.Value(connKey{}).(*Conn); ok {
380-
if c.nprogr++; c.nprogr%16 == 0 {
384+
if c.gosched++; c.gosched%16 == 0 {
381385
runtime.Gosched()
382386
}
383387
if c.interrupt.Err() != nil {

func.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,10 @@ func returnArgs(p *[]Value) {
284284
}
285285

286286
type aggregateFunc struct {
287-
ctx Context
288-
arg []Value
289287
next func() (struct{}, bool)
290288
stop func()
289+
ctx Context
290+
arg []Value
291291
}
292292

293293
func (a *aggregateFunc) Step(ctx Context, arg ...Value) {

stmt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func (s *Stmt) Busy() bool {
106106
//
107107
// https://sqlite.org/c3ref/step.html
108108
func (s *Stmt) Step() bool {
109-
s.c.checkInterrupt(s.c.handle)
109+
s.c.checkInterrupt()
110110
rc := res_t(s.c.call("sqlite3_step", stk_t(s.handle)))
111111
switch rc {
112112
case _ROW:

0 commit comments

Comments
 (0)