This is an automated email from the ASF dual-hosted git repository.

abhishekrb19 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 5d84de19bf9 perf: materialize child emitters in ComposingEmitter to 
avoid per-event Guice resolution (#19942)
5d84de19bf9 is described below

commit 5d84de19bf9a911f5d601b9f3b729ee27c04c30c
Author: Rushikesh Bankar <[email protected]>
AuthorDate: Wed Aug 12 22:56:24 2026 +0530

    perf: materialize child emitters in ComposingEmitter to avoid per-event 
Guice resolution (#19942)
    
    Fixed lock contention on the metrics emit path when using the composing 
emitter (druid.emitter=composing). Child emitters are now resolved once at 
startup instead of on every emitted event, which previously caused significant 
monitor contention on nodes emitting metrics at high volume.
---
 .../server/emitter/ComposingEmitterModule.java     | 18 ++++---------
 .../initialization/ComposingEmitterModuleTest.java | 31 ++++++++++++++++++++++
 2 files changed, 36 insertions(+), 13 deletions(-)

diff --git 
a/server/src/main/java/org/apache/druid/server/emitter/ComposingEmitterModule.java
 
b/server/src/main/java/org/apache/druid/server/emitter/ComposingEmitterModule.java
index 254f86193a1..a830b7d6449 100644
--- 
a/server/src/main/java/org/apache/druid/server/emitter/ComposingEmitterModule.java
+++ 
b/server/src/main/java/org/apache/druid/server/emitter/ComposingEmitterModule.java
@@ -19,8 +19,7 @@
 
 package org.apache.druid.server.emitter;
 
-import com.google.common.base.Function;
-import com.google.common.collect.Lists;
+import com.google.common.collect.ImmutableList;
 import com.google.inject.Binder;
 import com.google.inject.Injector;
 import com.google.inject.Key;
@@ -55,17 +54,10 @@ public class ComposingEmitterModule implements DruidModule
   {
     log.info("Creating Composing Emitter with %s", config.getEmitters());
 
-    List<Emitter> emitters = Lists.transform(
-        config.getEmitters(),
-        new Function<>()
-        {
-          @Override
-          public Emitter apply(String s)
-          {
-            return injector.getInstance(Key.get(Emitter.class, 
Names.named(s)));
-          }
-        }
-    );
+    List<Emitter> emitters = config.getEmitters()
+                                   .stream()
+                                   .map(s -> 
injector.getInstance(Key.get(Emitter.class, Names.named(s))))
+                                   .collect(ImmutableList.toImmutableList());
 
     return new ComposingEmitter(emitters);
   }
diff --git 
a/server/src/test/java/org/apache/druid/initialization/ComposingEmitterModuleTest.java
 
b/server/src/test/java/org/apache/druid/initialization/ComposingEmitterModuleTest.java
index ab0a5eb9119..4f372b9bc6b 100644
--- 
a/server/src/test/java/org/apache/druid/initialization/ComposingEmitterModuleTest.java
+++ 
b/server/src/test/java/org/apache/druid/initialization/ComposingEmitterModuleTest.java
@@ -28,6 +28,7 @@ import com.google.inject.name.Names;
 import org.apache.druid.guice.DruidGuiceExtensions;
 import org.apache.druid.guice.LifecycleModule;
 import org.apache.druid.java.util.emitter.core.Emitter;
+import org.apache.druid.java.util.emitter.core.Event;
 import org.apache.druid.server.emitter.ComposingEmitterConfig;
 import org.apache.druid.server.emitter.ComposingEmitterModule;
 import org.easymock.EasyMock;
@@ -70,6 +71,36 @@ public class ComposingEmitterModuleTest
     EasyMock.verify(config, emitter, injector);
   }
 
+  @Test
+  public void testEmitDoesNotReResolveChildEmitters()
+  {
+    ComposingEmitterConfig config = 
EasyMock.createMock(ComposingEmitterConfig.class);
+    
EasyMock.expect(config.getEmitters()).andReturn(Collections.singletonList(testEmitterType)).anyTimes();
+
+    Event event = EasyMock.createNiceMock(Event.class);
+
+    Emitter child = EasyMock.createMock(Emitter.class);
+    child.start();
+    child.emit(event);
+    EasyMock.expectLastCall().times(3);
+    EasyMock.replay(child, event);
+
+    Injector injector = EasyMock.createMock(Injector.class);
+    // The child emitter must be resolved from the injector exactly once (at 
construction), not once per emitted event.
+    EasyMock.expect(injector.getInstance(Key.get(Emitter.class, 
Names.named(testEmitterType))))
+            .andReturn(child)
+            .once();
+    EasyMock.replay(config, injector);
+
+    Emitter composingEmitter = new ComposingEmitterModule().getEmitter(config, 
injector);
+    composingEmitter.start();
+    composingEmitter.emit(event);
+    composingEmitter.emit(event);
+    composingEmitter.emit(event);
+
+    EasyMock.verify(config, injector, child);
+  }
+
   @Test
   public void testGetEmitterViaRealGuice()
   {


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to