-
Notifications
You must be signed in to change notification settings - Fork 17
Move compute-heavy endpoints off event loop on to worker threads #2310
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
base: main
Are you sure you want to change the base?
Move compute-heavy endpoints off event loop on to worker threads #2310
Conversation
| mainRouter.post(V2_IDENTITY_BUCKETS.toString()).handler(bodyHandler).handler(auth.handleV1( | ||
| rc -> encryptedPayloadHandler.handle(rc, this::handleBucketsV2), Role.MAPPER)); | ||
| rc -> encryptedPayloadHandler.handleAsync(rc, this::handleBucketsV2Async), Role.MAPPER)); | ||
| mainRouter.post(V2_IDENTITY_MAP.toString()).handler(bodyHandler).handler(auth.handleV1( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You don't have to do all this.. please just swap the existing handler with blockingHandler, ordered = false: https://vertx.io/docs/apidocs/io/vertx/ext/web/Route.html#blockingHandler(io.vertx.core.Handler,boolean)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why I didn’t use blockingHandler
- It runs on Vert.x’s default worker pool, and it cannot be configured to run on a different pool
- The default worker pool also handles store sync operations (e.g., RotatingStoreVerticle and CloudSyncVerticle from uid2 shared), some of which are IO bound
- Without a way to isolate these tasks, IO bound tasks might block the worker threads, slowing down processing of batch requests
- This interference would also distort queue metrics (both wait time and queue length), as the queue would reflect not only request load but also other background tasks. That would make alerts (and potential HPA scaling based on them) flakier
…ol' of github.com:IABTechLab/uid2-operator into srm-UID2-6480-move-compute-heavy-endpoints-to-worker-pool
…ol' of github.com:IABTechLab/uid2-operator into srm-UID2-6480-move-compute-heavy-endpoints-to-worker-pool
|
|
||
| // Create shared compute pool for CPU-intensive operations | ||
| final int computePoolSize = config.getInteger(Const.Config.ComputePoolThreadCountProp, Math.max(1, Runtime.getRuntime().availableProcessors() - 2)); | ||
| final WorkerExecutor computeWorkerPool = vertx.createSharedWorkerExecutor("compute", computePoolSize); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Maybe rename the compute worker pool with a meaningful name (eg: "cpu intensive compute")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed the compute pool to compute-heavy-request pool
| // Create shared compute pool for CPU-intensive operations | ||
| final int computePoolSize = config.getInteger(Const.Config.ComputePoolThreadCountProp, Math.max(1, Runtime.getRuntime().availableProcessors() - 2)); | ||
| final WorkerExecutor computeWorkerPool = vertx.createSharedWorkerExecutor("compute", computePoolSize); | ||
| LOGGER.info("Created compute worker pool with size: {}", computePoolSize); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe log the name of the worker pool as we might add more worker pools in the future for different usage
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
renamed the compute pool to compute-heavy-request pool
|
|
||
| Supplier<Verticle> operatorVerticleSupplier = () -> { | ||
| UIDOperatorVerticle verticle = new UIDOperatorVerticle(configStore, config, this.clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, getKeyManager(), saltProvider, optOutStore, Clock.systemUTC(), _statsCollectorQueue, new SecureLinkValidatorService(this.serviceLinkProvider, this.serviceProvider), this.shutdownHandler::handleSaltRetrievalResponse, this.uidInstanceIdProvider); | ||
| UIDOperatorVerticle verticle = new UIDOperatorVerticle(configStore, config, this.clientSideTokenGenerate, siteProvider, clientKeyProvider, clientSideKeypairProvider, getKeyManager(), saltProvider, optOutStore, Clock.systemUTC(), _statsCollectorQueue, new SecureLinkValidatorService(this.serviceLinkProvider, this.serviceProvider), this.shutdownHandler::handleSaltRetrievalResponse, this.uidInstanceIdProvider, computeWorkerPool); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Question (maybe also for @sunnywu @mcollins-ttd @vishalegbert-ttd ), do we prefer using dependency injection for the WorkerExecutor here, or should we simply pass the pool name?
Since vertx.createSharedWorkerExecutor("name") acts as a "get or create," we can easily fetch the shared pool internally without passing the object.
- Pros for DI: It makes mocking easier for unit tests.
- Cons: It might become annoying if we introduce multiple distinct pools in the future (e.g., separating the 'identity map' pool from other heavy compute endpoints), as we'd have to update constructor signatures for every new pool.
wdyt?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved through offline discussion.
Decision: Keep the DI paradigm we have now.
…ol' of github.com:IABTechLab/uid2-operator into srm-UID2-6480-move-compute-heavy-endpoints-to-worker-pool
…-compute-heavy-endpoints-to-worker-pool
…ol' of github.com:IABTechLab/uid2-operator into srm-UID2-6480-move-compute-heavy-endpoints-to-worker-pool
| this.createVertxEventLoopsMetric(); | ||
|
|
||
| // Create worker pool for compute-heavy requests (identity/map, key/sharing, key/bidstream) | ||
| final int computeHeavyRequestPoolSize = config.getInteger(Const.Config.ComputeHeavyRequestPoolThreadCountProp, Math.max(1, Runtime.getRuntime().availableProcessors() - 2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggests (Runtime.getRuntime().availableProcessors() - 2))/2 + 1
to correspond to yr recommendations of (vCPU count excluding 2 for other processes /2) + 1
Changes made:
Tests ran: