-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathtest-cached-prepare.scm
118 lines (97 loc) · 4.23 KB
/
test-cached-prepare.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
(use sql-de-lite)
(use miscmacros)
(use lru-cache)
;; Test cached statement performance. Tests below are normalized to
;; run in about the same amount of time (about 0.47 seconds).
(define prepare/cached
(let ((cache '()))
(lambda (db sql)
(or (alist-ref sql cache string=?)
(and-let* ((stmt (prepare db sql)))
(set! cache (cons (cons sql stmt)
cache))
stmt)))))
(define prepare/cached/ht
(let ((cache (make-hash-table string=?)))
(lambda (db sql)
(or (hash-table-ref/default cache sql #f)
(and-let* ((stmt (prepare db sql)))
(hash-table-set! cache sql stmt)
stmt)))))
(define lru-cache #f)
(define prepare/cached/lru
(let ((cache (make-lru-cache 100 string=? (lambda (sql stmt)
(finalize stmt)))))
(set! lru-cache cache)
(lambda (db sql)
(or (lru-cache-ref cache sql) ; note: reset not done
(and-let* ((stmt (prepare-transient db sql)))
(lru-cache-set! cache sql stmt)
stmt)))))
;; tested with schema:
;; create table cache(key text primary key, val text);
(call-with-database "a.db"
(lambda (db)
;; fill the cache with one useful then 50 dummy statements
(prepare/cached db "select * from cache;")
(dotimes (i 50)
(prepare/cached db (sprintf "select ~A;" i)))
;; select from front of alist
(time (repeat 950000 (prepare/cached db "select * from cache; ")))
;; select from back of alist (scan 50 statements)
(time (repeat 135000 (prepare/cached db "select * from cache;")))
;; prepare statement where schema must be checked (small schema)
(time (repeat 31000
(finalize (prepare-transient db "select * from cache;"))))
;; prepare statement not requiring schema
(time (repeat 47000
(finalize (prepare-transient db "select 1;"))))
;; -- After upgrading to sql-de-lite, speed penalty (800000 -> 480000).
;; -- It's because statement is now reset when it is pulled from cache,
;; -- which is not accounted for in other tests.
;; cached prepare statement where schema must be checked (small schema)
(time (repeat 480000
(prepare db "select * from cache;")))
;; cached prepare statement not requiring schema
(time (repeat 520000
(prepare db "select 1;")))
;;; rerun for hash cache
(print ":::::::::::::::::::::")
;; fill the hash cache with one useful then 50 dummy statements
(prepare/cached/ht db "select * from cache;")
(dotimes (i 50)
(prepare/cached/ht db (sprintf "select ~A;" i)))
;; Select random statements.
(time (repeat 950000 (prepare/cached/ht db "select * from cache; ")))
(time (repeat 950000 (prepare/cached/ht db "select * from cache;")))
(time (repeat 1050000 (prepare/cached/ht db "select 20;")))
;;; rerun for lru cache
(print ":::::::::::::::::::::")
(dotimes (i 50)
(prepare/cached/lru db (sprintf "select ~A;" i)))
;; Read MRU statement repeatedly.
(time (repeat 910000 (prepare/cached/lru db "select 0;")))
;; Alternate between two statements, simulating a random
;; lookup (LRU structure must be updated).
(time (dotimes (i 700000)
(prepare/cached/lru db (if (fx= (fxand i 1) 1)
"select 0;"
"select 1;"))))
(print "-- alternate between two statements, native egg cache")
(time (dotimes (i 430000)
(prepare db (if (fx= (fxand i 1) 1)
"select 0;"
"select 1;"))))
(lru-cache-flush! lru-cache)
)
)
#|
;; Confirms that string-append s allocates a new string
(let ((s "select * from cache;"))
(print "s = (string-append s): " (eq? s (string-append s)))
(print "(string-append s) = (string-append s): " (eq? (string-append s)
(string-append s))))
(print "literal strings eq?: " (eq? "select;" "select;"))
(let ((s ("static;")))
(string-set! s 0 #\t))
|#