-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
Description:
Currently, the Profiler._record_span method executes in the main application thread. It uses a threading.Lock to protect the buffer and, when the buffer is full, performs a synchronous flush to BeaverDB (file I/O) within the same thread.
In high-concurrency asyncio applications or CPU-intensive workloads, this design introduces two major performance bottlenecks:
- Thread Contention: The lock forces serialization of all span completions. If 1,000 tasks finish simultaneously, they must wait in line to record their data.
- I/O Latency: Flushing to disk (even if buffered) blocks the application's execution flow, causing unpredictable latency spikes in endpoint responses.
Proposed Solution:
Decouple the "recording" of a span from the "persistence" of that span. Use a lock-free, thread-safe queue to accept spans immediately, and move all file I/O operations to a dedicated daemon thread.
Tasks:
- Queue Implementation (
ferret/core.py):- Replace the
self._bufferlist andself._buffer_lockwith aqueue.SimpleQueue(unbounded) orqueue.Queue(bounded, to prevent OOM). - Update
_record_spanto simplyput()the span model into the queue. This operation is atomic and requires no explicit locking.
- Replace the
- Background Worker:
- Add a
_background_writermethod that runs in a loop, consuming items from the queue. - Implement batching logic inside the worker: wait for
buffer_sizeitems or a timeout (e.g., 0.5s) before writing toBeaverDB. - Start this worker as a
daemonthread inProfiler.__init__.
- Add a
- Graceful Shutdown:
- Update
Profiler.close()to send a "poison pill" or set athreading.Eventto stop the worker. - Ensure
close()waits (thread.join()) for the worker to finish flushing the remaining queue items before returning.
- Update
Acceptance Criteria:
_record_spanreturns immediately without acquiring locks or performing I/O.- Heavy loads (e.g., 10,000 spans/sec) do not block the main execution thread.
- All queued spans are successfully flushed to disk upon
profiler.close().
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels