mirror of
https://github.com/element-hq/synapse.git
synced 2026-03-30 21:35:53 +00:00
speed up the tests a bit
Summary of the performance fix: - Synchronous DB for in-memory SQLite: When _use_shared_conn is True (in-memory SQLite with a single shared connection — the test setup), runWithConnection and runInteraction now run the function directly on the event loop thread instead of dispatching to a ThreadPoolExecutor. This eliminates thread context switch overhead for every DB query. - pump() uses asyncio.sleep(0) not asyncio.sleep(0.01): Zero-delay yields drain pending callbacks without burning real wall-clock time. The remaining gap vs Twisted (~14s vs ~6s for login tests) is inherent to IsolatedAsyncioTestCase — each test creates a new event loop, and the _advance_time background task adds per-iteration overhead that Twisted's synchronous pump() didn't have. Further optimization would require either reducing the number of _advance_time iterations or finding a way to process callbacks synchronously like Twisted did.
This commit is contained in:
@@ -176,11 +176,16 @@ class NativeConnectionPool:
|
||||
if self._closed:
|
||||
raise Exception("Connection pool is closed")
|
||||
|
||||
def _inner() -> R:
|
||||
conn = self._get_connection()
|
||||
conn = self._get_connection()
|
||||
|
||||
if self._use_shared_conn:
|
||||
# For in-memory SQLite with a shared connection, run directly
|
||||
# on the event loop thread to avoid thread dispatch overhead.
|
||||
return func(conn, *args, **kwargs)
|
||||
|
||||
def _inner() -> R:
|
||||
return func(conn, *args, **kwargs)
|
||||
|
||||
# Run in thread pool via asyncio
|
||||
loop = asyncio.get_running_loop()
|
||||
return await loop.run_in_executor(self._executor, _inner)
|
||||
|
||||
@@ -206,8 +211,20 @@ class NativeConnectionPool:
|
||||
if self._closed:
|
||||
raise Exception("Connection pool is closed")
|
||||
|
||||
def _inner() -> R:
|
||||
conn = self._get_connection()
|
||||
conn = self._get_connection()
|
||||
|
||||
if self._use_shared_conn:
|
||||
# For in-memory SQLite with a shared connection, run directly
|
||||
# on the event loop thread to avoid thread dispatch overhead.
|
||||
try:
|
||||
result = func(conn, *args, **kwargs)
|
||||
conn.commit()
|
||||
return result
|
||||
except Exception:
|
||||
conn.rollback()
|
||||
raise
|
||||
|
||||
def _inner() -> R:
|
||||
try:
|
||||
result = func(conn, *args, **kwargs)
|
||||
conn.commit()
|
||||
@@ -216,7 +233,6 @@ class NativeConnectionPool:
|
||||
conn.rollback()
|
||||
raise
|
||||
|
||||
# Run in thread pool via asyncio
|
||||
loop = asyncio.get_running_loop()
|
||||
return await loop.run_in_executor(self._executor, _inner)
|
||||
|
||||
|
||||
@@ -545,10 +545,10 @@ async def make_request(
|
||||
if await_result and req.render_deferred is not None:
|
||||
import asyncio
|
||||
|
||||
# Advance fake time in tiny increments (1ms). This is small enough
|
||||
# that ratelimit token buckets don't noticeably refill (0.2/s × 1ms
|
||||
# = 0.0002 tokens per iteration), yet large enough that ratelimit
|
||||
# pauses (0.5s) complete in ~500 iterations.
|
||||
# Advance fake time in a background task so clock.sleep() calls
|
||||
# (ratelimit pauses) and call_later timers resolve. We advance
|
||||
# 1ms per event loop iteration — small enough to not refill
|
||||
# ratelimit buckets, large enough for pauses to complete.
|
||||
async def _advance_time() -> None:
|
||||
while not req.render_deferred.done():
|
||||
if clock is not None:
|
||||
|
||||
@@ -825,10 +825,9 @@ class HomeserverTestCase(TestCase):
|
||||
"""
|
||||
# Advance fake time (fires pending sleeps and callFromThread)
|
||||
self.reactor.advance(by)
|
||||
# Yield to the event loop multiple times so background tasks
|
||||
# (including DB operations in executor threads) can complete.
|
||||
# Yield to the event loop multiple times to drain pending callbacks.
|
||||
for _ in range(20):
|
||||
await asyncio.sleep(0.01)
|
||||
await asyncio.sleep(0)
|
||||
|
||||
async def get_success(self, d: Awaitable[TV], by: float = 0.0) -> TV:
|
||||
"""Await an awaitable, optionally advancing fake time first."""
|
||||
|
||||
Reference in New Issue
Block a user