Skip to content

Conversation

@benbroadaway
Copy link
Collaborator

@benbroadaway benbroadaway commented Dec 19, 2025

A nosy heap dump reveals we end up with 145 instances of ProcessKeyCache and 70+ instances of ProcessQueueManager.

Screenshot 2025-12-19 at 4 51 44 PM

Some are more used than others, but there's duplicate entries across the instances so there's duplicated lookups (unnecessary db traffic).

Screenshot 2025-12-19 at 5 20 02 PM

Annotating as @Singleton brings that down to 1 each, as one would expect. This should result in fewer calls to the DB and less memory usage by the cached data over all.

@benbroadaway benbroadaway requested review from a team, brig and ibodrov December 19, 2025 23:24
@benbroadaway
Copy link
Collaborator Author

This may be a just a piece of a larger oversight. Or I may be missing a point. Should all implementations of PayloadProcessor be singleton as well? They're not particularly expensive to create. But are they intentionally not singleton currently?

@brig
Copy link
Contributor

brig commented Dec 22, 2025

This may be a just a piece of a larger oversight. Or I may be missing a point. Should all implementations of PayloadProcessor be singleton as well? They're not particularly expensive to create. But are they intentionally not singleton currently?

interesting....

binder.bind(ProcessKeyCache.class).to(com.walmartlabs.concord.server.process.queue.ProcessKeyCache.class).in(SINGLETON);

  /** One instance per {@link Injector}. Also see {@code @}{@link Singleton}. */
  public static final Scope SINGLETON = new SingletonScope();

/**
 * Apply this to implementation classes when you want only one instance (per {@link Injector}) to be
 * reused for all injections for that binding.
 *
 * @author [email protected] (Bob Lee)
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RUNTIME)
@ScopeAnnotation
public @interface Singleton {}

with @singleton annotation:

10:55:22.385 [main] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@64b8f8f4 10:55:22.385 [main] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ProcessKeyCache created: 724612647 10:55:22.385 [main] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - Injector id=1604949791

without:

10:57:45.934 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@64b8f8f4
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ProcessKeyCache created: 1784527308
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - Injector id=588356547

10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@64b8f8f4
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ProcessKeyCache created: 1006259625
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - Injector id=588356547

10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@64b8f8f4
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ProcessKeyCache created: 805520003
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - Injector id=588356547

10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@64b8f8f4
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ProcessKeyCache created: 1977694546
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - Injector id=588356547

10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@64b8f8f4
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ProcessKeyCache created: 797605812
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - Injector id=588356547

10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@64b8f8f4
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ProcessKeyCache created: 541592470
10:57:45.935 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - Injector id=588356547

10:57:45.936 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ClassLoader: jdk.internal.loader.ClassLoaders$AppClassLoader@64b8f8f4
10:57:45.936 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - ProcessKeyCache created: 1686722530
10:57:45.936 [qtp29401411-56] [INFO ] [] c.w.c.s.p.queue.ProcessKeyCache - Injector id=588356547
....

@brig
Copy link
Contributor

brig commented Dec 22, 2025

looks like problem here:

we should not inject implementation.

so fix is:

import com.walmartlabs.concord.server.sdk.ProcessKeyCache;

and there is also: ProcessKeyCacheGaugeModule :)

@brig
Copy link
Contributor

brig commented Dec 22, 2025

@benbroadaway
Copy link
Collaborator Author

Ahh, unfortunate class name collision.

Also fixes the metric

# after executing 3 processes and restarting 1
$ curl -s http://localhost:8001/metrics | grep process_key_cache_ | grep -ve '^#' && echo
process_key_cache_miss_count 4.0
process_key_cache_hit_count 256.0

Copy link
Collaborator

@ibodrov ibodrov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comment, otherwise LGTM. Needs a better title?

import com.walmartlabs.concord.server.process.logs.ProcessLogManager;
import com.walmartlabs.concord.server.sdk.PartialProcessKey;
import com.walmartlabs.concord.server.sdk.ProcessKey;
import com.walmartlabs.concord.server.sdk.ProcessKeyCache;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What for?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The interface and implementation have the same class name ProcessKeyCache. And the implementation is in the server.queue package, so without importing either class, guice defaults to the implementation--which isn't configured as a singleton. The interface is explicitly bound in singleton scope.

@benbroadaway benbroadaway changed the title concord-server: use singleton ProcessKeyCache and ProcessQueueManager concord-server: inject ProcessKeyCache interface instead of implementation to utilize singleton scope Dec 22, 2025
@benbroadaway benbroadaway merged commit dbedfd6 into master Dec 22, 2025
4 checks passed
@benbroadaway benbroadaway deleted the bb/server-process-cache-singleton branch December 22, 2025 22:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants