Allow tracing memory allocation for indexing a change

Release-Notes: skip
Change-Id: Ie7c6571c64e9294fb701158d2f3d739674238185
(cherry picked from commit d99b511aae46e12cc2eefc686aa1ab560cb7e750)
diff --git a/java/com/google/gerrit/server/index/change/ChangeIndexer.java b/java/com/google/gerrit/server/index/change/ChangeIndexer.java
index 17401ec..bf83a1b 100644
--- a/java/com/google/gerrit/server/index/change/ChangeIndexer.java
+++ b/java/com/google/gerrit/server/index/change/ChangeIndexer.java
@@ -27,6 +27,8 @@
 import com.google.gerrit.exceptions.StorageException;
 import com.google.gerrit.extensions.events.ChangeIndexedListener;
 import com.google.gerrit.index.Index;
+import com.google.gerrit.metrics.proc.ThreadMXBeanFactory;
+import com.google.gerrit.metrics.proc.ThreadMXBeanInterface;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.index.IndexExecutor;
 import com.google.gerrit.server.index.StalenessCheckResult;
@@ -63,6 +65,7 @@
  */
 public class ChangeIndexer {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+  private static final ThreadMXBeanInterface threadMxBean = ThreadMXBeanFactory.create();
 
   public interface Factory {
     ChangeIndexer create(ListeningExecutorService executor, ChangeIndex index);
@@ -219,27 +222,40 @@
   }
 
   private void indexImpl(ChangeData cd) {
-    logger.atFine().log("Reindex change %d in index.", cd.getId().get());
-    for (Index<?, ChangeData> i : getWriteIndexes()) {
-      try (TraceTimer traceTimer =
-          TraceContext.newTimer(
-              "Reindexing change in index",
-              Metadata.builder()
-                  .changeId(cd.getId().get())
-                  .patchSetId(cd.currentPatchSet().number())
-                  .indexVersion(i.getSchema().getVersion())
-                  .build())) {
-        if (isFirstInsertForEntry.equals(IsFirstInsertForEntry.YES)) {
-          i.insert(cd);
-        } else {
-          i.replace(cd);
+    long memoryAtStart = 0;
+    if (logger.atFine().isEnabled()) {
+      memoryAtStart = threadMxBean.getCurrentThreadAllocatedBytes();
+      logger.atFine().log("Reindex change %d in index.", cd.getId().get());
+    }
+    try {
+      for (Index<?, ChangeData> i : getWriteIndexes()) {
+        try (TraceTimer traceTimer =
+            TraceContext.newTimer(
+                "Reindexing change in index",
+                Metadata.builder()
+                    .changeId(cd.getId().get())
+                    .patchSetId(cd.currentPatchSet().number())
+                    .indexVersion(i.getSchema().getVersion())
+                    .build())) {
+          if (isFirstInsertForEntry.equals(IsFirstInsertForEntry.YES)) {
+            i.insert(cd);
+          } else {
+            i.replace(cd);
+          }
+        } catch (RuntimeException e) {
+          throw new StorageException(
+              String.format(
+                  "Failed to reindex change %d in index version %d (current patch set = %d)",
+                  cd.getId().get(), i.getSchema().getVersion(), cd.currentPatchSet().number()),
+              e);
         }
-      } catch (RuntimeException e) {
-        throw new StorageException(
-            String.format(
-                "Failed to reindex change %d in index version %d (current patch set = %d)",
-                cd.getId().get(), i.getSchema().getVersion(), cd.currentPatchSet().number()),
-            e);
+      }
+    } finally {
+      if (logger.atFine().isEnabled()) {
+        long memAllocated = threadMxBean.getCurrentThreadAllocatedBytes() - memoryAtStart;
+        logger.atFine().log(
+            "Reindexing of change %d allocated %d bytes of memory.",
+            cd.getId().get(), memAllocated);
       }
     }
     fireChangeIndexedEvent(cd.project().get(), cd.getId().get());