perf(core): introduce three shared thread pools - Query, Write and Network#5805
perf(core): introduce three shared thread pools - Query, Write and Network#5805bluestreak01 merged 32 commits intomasterfrom
Conversation
|
can i suggest to rename pools:
Subjectively this is clearer to me. |
There was a problem hiding this comment.
Pull Request Overview
This PR refactors QuestDB’s threading model to introduce three shared worker pools (Network, Query, Write) in place of the single shared pool.
Key changes:
- Split single shared pool into distinct Network, Query, and Write pools
- Updated WorkerPoolManager, ServerConfiguration, and service bindings to route jobs to the correct pool
- Revised tests and property handling to support new pool configurations
Reviewed Changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| core/src/main/java/io/questdb/WorkerPoolManager.java | Introduce separate sharedPoolNetwork, sharedPoolQuery, sharedPoolWrite and specialized getInstanceNetwork/getInstanceWrite |
| core/src/main/java/io/questdb/PropServerConfiguration.java | Read legacy shared settings and configure three PropWorkerPoolConfiguration instances via configureSharedThreadPool |
| core/src/main/java/io/questdb/Services.java | Updated service factory methods to call getInstanceNetwork/getInstanceWrite |
| core/src/main/java/io/questdb/ServerMain.java | Assign engine maintenance, query, writer, and housekeeping jobs to the appropriate shared pools |
| core/src/main/java/io/questdb/ServerConfiguration.java | Added getNetworkWorkerPoolConfiguration, getQueryWorkerPoolConfiguration, getWriteWorkerPoolConfiguration |
| core/src/main/java/io/questdb/cutlass/line/tcp | Renamed IOWorkerPoolConfiguration to NetworkWorkerPoolConfiguration across interfaces and wrappers |
| core/src/test/java/... | Adjusted tests to call new pool getters and updated expected default property outputs |
Comments suppressed due to low confidence (1)
core/src/main/java/io/questdb/PropServerConfiguration.java:1920
- The assignment
this.metricsis incorrect and will not compile, asPropServerConfigurationhas nometricsfield of typeWorkerPoolConfiguration.Metrics. You should assign a validMetricsenum value (e.g.Metrics.ENABLEDorMetrics.DISABLED) or retrieve it from the server's metrics configuration. For example:
poolConfiguration.metrics = config.getMetricsConfiguration().isEnabled() ? Metrics.ENABLED : Metrics.DISABLED; poolConfiguration.metrics = this.metrics;
There was a problem hiding this comment.
a lot more work is required here:
- parameter and field names everywhere need to be reviewed now that "shared pool" is no more
- there is proliferated confusion as to what "worker" count is meant to represent, wrong counts being passed around and parameter names are not helping
- we probably need some sort of fuzz test that boostraps unequal size pools and executes parallel queries on them, for example writer pool could be 4 and query pool could be 10. SQL may partition its data structures for 4 workers and will have 10 workers executing, causing chaos
- i observed weird boostrap, on 12 core laptop, network pool = 12, query pool = 12, wirter pool = 18? why 18?
…worker pool configuration method to better distinguish between network, query, and write worker pools as part of a thread pooling performance optimization
|
Hey @bluestreak01, this PR is now ready for a second look
I renamed parameters and fields everywhere to be
I added test
I changed the writer pool to 12. It used to be 50% more than the other pool because it's not supposed to be CPU-bound, but I decided against it now to avoid oversaturating the IO. |
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis change refactors the worker pool configuration system by splitting the previously monolithic shared worker pool into three specialized pools: network, query, and write. It updates configuration files, interfaces, and implementations to support these pools, and propagates this separation throughout the codebase and tests. Numerous method signatures, constructors, and internal logic are updated to use the new shared query worker count, and tests are adjusted to accommodate these changes. Changes
Sequence Diagram(s)sequenceDiagram
participant Config as ServerConfiguration
participant WorkerMgr as WorkerPoolManager
participant Service as Services
participant Job as Job/Processor
Config->>WorkerMgr: getNetworkWorkerPoolConfiguration()
Config->>WorkerMgr: getQueryWorkerPoolConfiguration()
Config->>WorkerMgr: getWriteWorkerPoolConfiguration()
WorkerMgr->>WorkerMgr: create shared pools (network, query, write)
Service->>WorkerMgr: getSharedNetworkPool()
Service->>WorkerMgr: getInstanceWrite()
Service->>Job: instantiate with sharedQueryWorkerCount
Job->>Job: run using correct pool (network/query/write)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes ✨ Finishing Touches🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
|
@CodeRabbit please review |
|
@bluestreak01 I'll review this PR which introduces the three shared thread pools architecture change. This is a significant modification to QuestDB's threading strategy that deserves careful examination. 🐰 ✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (4)
core/src/test/java/io/questdb/test/griffin/engine/functions/bool/WithinGeohashFunctionFactoryTest.java (1)
341-346: Duplicate of previous remarkThe second expectation string has the same hard-coded
workers: 2; please apply the same adjustment.core/src/main/java/io/questdb/ServerMain.java (1)
428-432: FlushQueryCacheJob should be assigned to the query pool.This job deals with query caching and belongs on the query pool rather than the network pool.
core/src/main/java/io/questdb/DefaultServerConfiguration.java (1)
152-171: Incomplete implementation of WorkerPoolConfiguration interface.The DefaultWorkerPoolConfiguration class only implements
getPoolName()andgetWorkerCount(). Other interface methods may return default values which could affect worker affinity, sleep thresholds, and metric registration.core/src/main/java/io/questdb/WorkerPoolManager.java (1)
128-135: Log messages should indicate pool type.The log messages are ambiguous as they all use the same prefix. Include the pool type in the message to clearly differentiate in logs.
🧹 Nitpick comments (11)
core/src/test/java/io/questdb/test/griffin/LatestByTest.java (1)
180-185: Hard-coding the expected worker count makes the test brittle
workers: 2is embedded directly in the expected plan string. If the defaultsharedQueryWorkerCountis changed via configuration or future refactor, this assertion will fail for reasons unrelated to query logic. Consider deriving the worker count from the active configuration (e.g.SharedWorkerPool.getWorkerCount()) or asserting via a regex such asworkers: \\d+.core/src/test/java/io/questdb/test/griffin/engine/functions/bool/WithinGeohashFunctionFactoryTest.java (1)
283-288: Same brittleness as above – avoid hard-wiringworkers: 2For maintainability, assert against
workers: \\d+or build the string with the actual query-worker-pool size at runtime.core/src/main/resources/io/questdb/site/conf/server.conf (1)
25-30: Consider clarifying the precedence behavior.The configuration shows both specific pool configurations (lines 8, 14, 20) and the default configuration (line 26). It would be helpful to clarify in the documentation how these interact - does the default value only apply when specific pool values are not set?
Consider adding a comment explaining the precedence behavior:
-# Default number of worker threads in Network, Query and Write shared pools. Single value to configure all three pools sizes. +# Default number of worker threads in Network, Query and Write shared pools. Single value to configure all three pools sizes. +# This value is used when specific pool configurations (shared.network.worker.count, shared.query.worker.count, shared.write.worker.count) are not set.core/src/main/java/io/questdb/DynamicPropServerConfiguration.java (2)
358-361: Add missing non-reloadable comment for consistency.The method implementation is correct, but it's missing the "// nested object is kept non-reloadable" comment that appears in other similar methods like
getNetworkWorkerPoolConfiguration()andgetWalApplyPoolConfiguration().@Override public WorkerPoolConfiguration getQueryWorkerPoolConfiguration() { + // nested object is kept non-reloadable return serverConfig.get().getQueryWorkerPoolConfiguration(); }
363-366: Add missing non-reloadable comment for consistency.The method implementation is correct, but it's also missing the "// nested object is kept non-reloadable" comment for consistency with other similar methods.
@Override public WorkerPoolConfiguration getWriteWorkerPoolConfiguration() { + // nested object is kept non-reloadable return serverConfig.get().getWriteWorkerPoolConfiguration(); }core/src/test/java/io/questdb/test/cutlass/pgwire/PGJobContextTest.java (4)
139-141: Consider using specific imports instead of wildcards for better code clarity.While wildcard imports reduce verbosity, specific imports make it clearer which methods are being used and help avoid potential naming conflicts.
-import static io.questdb.test.tools.TestUtils.*; -import static org.junit.Assert.*; +import static io.questdb.test.tools.TestUtils.assertResultSet; +import static org.junit.Assert.assertNotNull;
3812-3874: Fix comment inconsistency and excellent test isolation.The implementation correctly sets
sharedQueryWorkerCount = 2and properly cleans up in the finally block. However, the comment mentions "Set to 1" while actually setting to 2.- sharedQueryWorkerCount = 2; // Set to 1 to enable parallel query plans + sharedQueryWorkerCount = 2; // Set to 2 to enable parallel query plansThe expected query plans correctly reflect the parallel execution with "Async Filter workers: 2", and the try-finally pattern ensures proper test isolation.
3892-3923: Fix comment inconsistency.Same issue as the previous method - the comment mentions "Set to 1" while actually setting to 2.
- sharedQueryWorkerCount = 2; // Set to 1 to enable parallel query plans + sharedQueryWorkerCount = 2; // Set to 2 to enable parallel query plansGood descriptive cleanup comment and correct expected query plan with "Async Filter workers: 2".
3804-3881: Fix comment inconsistency.Same comment issue as the previous methods - mentions "Set to 1" while setting to 2.
- sharedQueryWorkerCount = 2; // Set to 1 to enable parallel query plans + sharedQueryWorkerCount = 2; // Set to 2 to enable parallel query plansThe test comprehensively covers multiple scenarios and correctly expects "Async Filter workers: 2" in the query plan.
core/src/main/java/io/questdb/PropServerConfiguration.java (2)
1919-1944: Good refactoring to reduce code duplication.The helper method effectively consolidates the shared thread pool configuration logic. Consider using a builder pattern or configuration object in the future if more parameters are added, as the method signature is already quite long.
1913-1916: Consider aligning field name with method name.The method
getNetworkWorkerPoolConfiguration()returnslineTcpIOWorkerPoolConfiguration. For consistency, consider renaming the field tolineTcpNetworkWorkerPoolConfigurationor keeping the method name asgetIOWorkerPoolConfiguration().
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
[PR Coverage check]😍 pass : 265 / 279 (94.98%) file detail
|
This PR changes default QuestDB threading strategy. Instead of single shared pool there will be three shared thread pools:
tandem: https://github.com/questdb/questdb-enterprise/pull/645