-
-
Notifications
You must be signed in to change notification settings - Fork 702
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
Research: how much overhead does the n=1 time limit have? #1679
Comments
Lines 118 to 122 in 1a7750e
ms < 50 :
Setting(
"facet_suggest_time_limit_ms",
50,
"Time limit for calculating a suggested facet",
), |
So it looks like even for facet suggestion |
How long does it take for SQLite to execute 1000 opcodes anyway? |
This is weird: import sqlite3
db = sqlite3.connect(":memory:")
i = 0
def count():
global i
i += 1
db.set_progress_handler(count, 1)
db.execute("""
with recursive counter(x) as (
select 0
union
select x + 1 from counter
)
select * from counter limit 10000;
""")
print(i) Outputs
|
Here's the Python-C implementation of It calls https://www.sqlite.org/c3ref/progress_handler.html says:
So maybe VM-steps and virtual machine instructions are different things? |
Posed a question about that here: https://sqlite.org/forum/forumpost/de9ff10fa7 |
David Raymond solved it there: https://sqlite.org/forum/forumpost/330c8532d8a88bcd
Sure enough, adding that gets the VM steps number up to 190,007 which is close enough that I'm happy. |
OK here's a microbenchmark script: import sqlite3
import timeit
db = sqlite3.connect(":memory:")
db_with_progress_handler_1 = sqlite3.connect(":memory:")
db_with_progress_handler_1000 = sqlite3.connect(":memory:")
db_with_progress_handler_1.set_progress_handler(lambda: None, 1)
db_with_progress_handler_1000.set_progress_handler(lambda: None, 1000)
def execute_query(db):
cursor = db.execute("""
with recursive counter(x) as (
select 0
union
select x + 1 from counter
)
select * from counter limit 10000;
""")
list(cursor.fetchall())
print("Without progress_handler")
print(timeit.timeit(lambda: execute_query(db), number=100))
print("progress_handler every 1000 ops")
print(timeit.timeit(lambda: execute_query(db_with_progress_handler_1000), number=100))
print("progress_handler every 1 op")
print(timeit.timeit(lambda: execute_query(db_with_progress_handler_1), number=100)) Results:
So running every 1000 ops makes almost no difference at all, but running every single op is a 3.2x performance degradation. |
Here's another microbenchmark that measures how many nanoseconds it takes to run 1,000 vmops: import sqlite3
import time
db = sqlite3.connect(":memory:")
i = 0
out = []
def count():
global i
i += 1000
out.append(((i, time.perf_counter_ns())))
db.set_progress_handler(count, 1000)
print("Start:", time.perf_counter_ns())
all = db.execute("""
with recursive counter(x) as (
select 0
union
select x + 1 from counter
)
select * from counter limit 10000;
""").fetchall()
print("End:", time.perf_counter_ns())
print()
print("So how long does it take to execute 1000 ops?")
prev_time_ns = None
for i, time_ns in out:
if prev_time_ns is not None:
print(time_ns - prev_time_ns, "ns")
prev_time_ns = time_ns Running it:
87596ns is 0.087596ms - so even a measure rate of every 1000 ops is easily finely grained enough to capture differences of less than 0.1ms. If anything I could bump that default 1000 up - and I can definitely eliminate the |
Oh interesting, it turns out there is ONE place in the code that sets the Lines 224 to 226 in 4e47a2d
|
I'm going to change the original logic to set n=1 for times that are |
datasette/datasette/utils/__init__.py
Lines 181 to 200 in 1a7750e
How often do I set a time limit of 50 or less? How much slower does it go thanks to this code?
The text was updated successfully, but these errors were encountered: