sk0x50 commented on code in PR #6100:
URL: https://github.com/apache/ignite-3/pull/6100#discussion_r2163265779


##########
modules/metastorage-api/src/main/java/org/apache/ignite/internal/metastorage/timebag/TimeBagImpl.java:
##########
@@ -0,0 +1,367 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.metastorage.timebag;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.PriorityQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+class TimeBagImpl implements TimeBag {
+    /** Lock. */
+    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+
+    /** Global stopwatch. */
+    private final IgniteStopwatch globalStopwatch;
+
+    /** Measurement unit. */
+    private final TimeUnit measurementUnit;
+
+    /** List of global stages (guarded by {@code lock}). */
+    private final List<CompositeStage> stages;
+
+    /** List of current local stages separated by threads (guarded by {@code 
lock}). */
+    private Map<String, List<Stage>> localStages;
+
+    /** Last seen global stage by thread. */
+    private final ThreadLocal<CompositeStage> tlLastSeenStage = new 
ThreadLocal<>();
+
+    /** Thread-local stopwatch. */
+    private final ThreadLocal<IgniteStopwatch> tlStopwatch = 
ThreadLocal.withInitial(IgniteStopwatch::createUnstarted);
+
+    /**
+     * Creates a new {@link TimeBag} with specified measurement unit.
+     *
+     * @param started Flag indicating whether the time bag is started or not.
+     * @param measurementUnit Measurement unit.
+     */
+    TimeBagImpl(boolean started, TimeUnit measurementUnit) {
+        this.stages = new ArrayList<>();
+        this.localStages = new ConcurrentHashMap<>();
+        this.measurementUnit = measurementUnit;
+        this.globalStopwatch = started ? IgniteStopwatch.createStarted() : 
IgniteStopwatch.createUnstarted();
+
+        CompositeStage initStage = new CompositeStage("", 0, new HashMap<>(), 
measurementUnit);
+
+        this.stages.add(initStage);
+
+        tlLastSeenStage.set(initStage);
+    }
+
+    /**
+     * Returns the last completed global stage.
+     */
+    private CompositeStage lastCompletedGlobalStage() {
+        return stages.get(stages.size() - 1);
+    }
+
+    @Override
+    public void start() {
+        lock.writeLock().lock();
+
+        try {
+            globalStopwatch.start();
+        } finally {
+            lock.writeLock().unlock();
+        }
+    }
+
+    /**
+     * Finishes the global stage with given description and resets the local 
stages.
+     *
+     * @param description Description.
+     */
+    @Override
+    public void finishGlobalStage(String description) {
+        lock.writeLock().lock();
+
+        try {
+            stages.add(
+                    new CompositeStage(
+                            description,
+                            globalStopwatch.elapsed(measurementUnit),
+                            Collections.unmodifiableMap(localStages),
+                            measurementUnit
+                    )
+            );
+
+            localStages = new ConcurrentHashMap<>();
+
+            globalStopwatch.reset().start();
+        } finally {
+            lock.writeLock().unlock();
+        }
+    }
+
+    /**
+     * Finishes the local stage with given description.
+     *
+     * @param description Description.
+     */
+    @Override
+    public void finishLocalStage(String description) {
+        lock.readLock().lock();
+
+        try {
+            CompositeStage lastSeen = tlLastSeenStage.get();
+            CompositeStage lastCompleted = lastCompletedGlobalStage();
+            IgniteStopwatch localStopWatch = tlStopwatch.get();
+
+            Stage stage;
+
+            // We see this stage first time, get elapsed time from last 
completed global stage and start tracking local.
+            if (lastSeen != lastCompleted) {
+                stage = new Stage(description, 
globalStopwatch.elapsed(measurementUnit), measurementUnit);
+
+                tlLastSeenStage.set(lastCompleted);
+            } else {
+                stage = new Stage(description, 
localStopWatch.elapsed(measurementUnit), measurementUnit);
+            }
+
+            localStopWatch.reset().start();
+
+            // Associate local stage with current thread name.
+            String threadName = Thread.currentThread().getName();
+
+            localStages.computeIfAbsent(threadName, t -> new 
ArrayList<>()).add(stage);
+        } finally {
+            lock.readLock().unlock();
+        }
+    }
+
+    /**
+     * Returns short name of desired measurement unit.
+     *
+     * @return Short name of desired measurement unit.
+     */
+    private static String measurementUnitShort(TimeUnit measurementUnit) {
+        switch (measurementUnit) {
+            case MILLISECONDS:
+                return "ms";
+            case SECONDS:
+                return "s";
+            case NANOSECONDS:
+                return "ns";
+            case MICROSECONDS:
+                return "mcs";

Review Comment:
   Thanks. I will update the code according to your suggestion.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: notifications-unsubscr...@ignite.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to