Skip to content
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

[CASSANDRA-20250][trunk] Optimize Counter, Meter and Histogram metrics using thread local counters #3927

Open
wants to merge 25 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3a54e55
A very basic sketch of thread local counter metric
Feb 6, 2025
3baa8f9
remove double init
Feb 6, 2025
cc1af32
minor fixes
Feb 6, 2025
912fdc9
fix optimistic locking logic: we should compare immutable values
Feb 6, 2025
a5360ee
add piggyback array implementation which rely on external volatile vi…
Feb 6, 2025
383f3a0
replace codahale Meter and Counter with ThreadLocal implementations
Feb 10, 2025
d47f2a8
integrate CASSANDRA-19332 patch for Meter, fix formatting
Feb 10, 2025
e40aa36
fix addNonStatic method - do not do a thread local looku
Feb 10, 2025
280b6f2
add cache polution emulation to MetersBench
Feb 11, 2025
692988c
added more notes about possible optimizations
Feb 11, 2025
151c836
remove EWMA as a separate object, move calculations to ThreadLocalExp…
Feb 11, 2025
d584147
add unit tests to check Meter behavior using codahale Meter as a stan…
Feb 11, 2025
399bf08
replace codahale Timer with ThreadLocalTimer
Feb 13, 2025
bdfec9d
replace codahale Histogram with ThreadLocalHistogram
Feb 13, 2025
d4abba2
use shared non-thread local double[] for rates to improve memory loca…
Feb 15, 2025
373cb31
Meters may have different tick values if they created at different mo…
Feb 15, 2025
e7adcef
use PhantomReferences to recycle metric IDs and ThreadLocalMetrics ob…
Feb 20, 2025
5a2d662
add javadoc for ThreadLocalMetrics, fix some concurrency issues relat…
Feb 23, 2025
1c214b1
add javadoc for ThreadLocalMeter, use BitSet for free rate group ids
Feb 23, 2025
caba39a
add more javadocs, improve test coverage, move LongAdderCounter to tests
Feb 24, 2025
4c802d1
few more asserts
Feb 24, 2025
e4f26c9
Inherit ThreadLocal metric classes from Dropwizard metrics to provide…
Mar 2, 2025
2fa62ad
Exclude "ThreadLocalMetrics-Cleaner" thread from unit test checks
Mar 2, 2025
a671f80
Inherit AtomicLongCounter from Dropwizard Counter as well
Mar 2, 2025
f82e2d6
use different name for AtomicLongCounter field to be able to null par…
Mar 2, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.codahale.metrics.Timer.Context;
import org.apache.cassandra.metrics.Timer.Context;
import net.nicoulaj.compilecommand.annotations.DontInline;
import org.apache.cassandra.concurrent.Interruptible;
import org.apache.cassandra.concurrent.Interruptible.TerminateException;
Expand Down Expand Up @@ -338,7 +338,7 @@ void awaitAvailableSegment(CommitLogSegment currentAllocatingFrom)
{
do
{
WaitQueue.Signal prepared = segmentPrepared.register(commitLog.metrics.waitingOnSegmentAllocation.time(), Context::stop);
WaitQueue.Signal prepared = segmentPrepared.register(commitLog.metrics.waitingOnSegmentAllocation.startTime(), Context::stop);
if (availableSegment == null && allocatingFrom == currentAllocatingFrom)
prepared.awaitUninterruptibly();
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import org.apache.cassandra.utils.concurrent.Semaphore;
import org.apache.cassandra.utils.concurrent.WaitQueue;

import static com.codahale.metrics.Timer.Context;
import org.apache.cassandra.metrics.Timer.Context;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.MINUTES;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import com.google.common.annotations.VisibleForTesting;
import org.cliffc.high_scale_lib.NonBlockingHashMap;

import com.codahale.metrics.Timer;
import org.apache.cassandra.metrics.Timer;
import net.openhft.chronicle.core.util.ThrowingFunction;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.Mutation;
Expand Down Expand Up @@ -355,7 +355,7 @@ synchronized void sync(boolean flush)

if (flush || close)
{
try (Timer.Context ignored = CommitLog.instance.metrics.waitingOnFlush.time())
try (Timer.Context ignored = CommitLog.instance.metrics.waitingOnFlush.startTime())
{
flush(startMarker, sectionEnd);
}
Expand Down Expand Up @@ -736,7 +736,7 @@ void markWritten()

void awaitDiskSync(Timer waitingOnCommit)
{
try (Timer.Context ignored = waitingOnCommit.time())
try (Timer.Context ignored = waitingOnCommit.startTime())
{
segment.waitForSync(position);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ protected void maybeWaitForSync(CommitLogSegment.Allocation alloc)
if (lastSyncedAt < expectedSyncTime)
{
pending.incrementAndGet();
awaitSyncAt(expectedSyncTime, commitLog.metrics.waitingOnCommit.time());
awaitSyncAt(expectedSyncTime, commitLog.metrics.waitingOnCommit.startTime());
pending.decrementAndGet();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.codahale.metrics.Meter;
import org.apache.cassandra.metrics.Meter;
import net.openhft.chronicle.core.util.ThrowingSupplier;
import org.apache.cassandra.cache.AutoSavingCache;
import org.apache.cassandra.concurrent.ExecutorFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.util.concurrent.Runnables;

import com.codahale.metrics.Counter;
import org.apache.cassandra.metrics.Counter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

import com.google.common.annotations.VisibleForTesting;

import com.codahale.metrics.Counter;
import org.apache.cassandra.metrics.Counter;
import com.codahale.metrics.Snapshot;
import org.apache.cassandra.auth.CassandraAuthorizer;
import org.apache.cassandra.config.DatabaseDescriptor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

package org.apache.cassandra.db.virtual.model;

import com.codahale.metrics.Counter;
import org.apache.cassandra.metrics.Counter;
import com.codahale.metrics.Metric;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

package org.apache.cassandra.db.virtual.model;

import com.codahale.metrics.Histogram;
import org.apache.cassandra.metrics.Histogram;
import com.codahale.metrics.Metric;
import com.codahale.metrics.Snapshot;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

package org.apache.cassandra.db.virtual.model;

import com.codahale.metrics.Meter;
import org.apache.cassandra.metrics.Meter;
import com.codahale.metrics.Metric;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;
Expand Down
8 changes: 4 additions & 4 deletions src/java/org/apache/cassandra/db/virtual/model/MetricRow.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@

package org.apache.cassandra.db.virtual.model;

import com.codahale.metrics.Counter;
import org.apache.cassandra.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import org.apache.cassandra.metrics.Histogram;
import org.apache.cassandra.metrics.Meter;
import com.codahale.metrics.Metric;
import com.codahale.metrics.Timer;
import org.apache.cassandra.metrics.Timer;
import org.apache.cassandra.metrics.CassandraMetricsRegistry;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
package org.apache.cassandra.db.virtual.model;

import com.codahale.metrics.Metric;
import com.codahale.metrics.Timer;
import org.apache.cassandra.metrics.Timer;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@

import java.util.concurrent.TimeUnit;

import com.codahale.metrics.Meter;
import com.codahale.metrics.Timer;
import org.apache.cassandra.metrics.Meter;
import org.apache.cassandra.metrics.Timer;
import org.apache.cassandra.index.sai.utils.IndexIdentifier;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
*/
package org.apache.cassandra.index.sai.metrics;

import com.codahale.metrics.Counter;
import org.apache.cassandra.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Timer;
import org.apache.cassandra.metrics.Histogram;
import org.apache.cassandra.metrics.Timer;
import org.apache.cassandra.index.sai.StorageAttachedIndex;
import org.apache.cassandra.index.sai.memory.MemtableIndexManager;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@

import java.util.concurrent.TimeUnit;

import com.codahale.metrics.Counter;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Timer;
import org.apache.cassandra.metrics.Counter;
import org.apache.cassandra.metrics.Histogram;
import org.apache.cassandra.metrics.Timer;
import org.apache.cassandra.index.sai.QueryContext;
import org.apache.cassandra.schema.TableMetadata;
import org.apache.cassandra.tracing.Tracing;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import java.nio.ByteBuffer;
import java.util.List;

import com.codahale.metrics.Histogram;
import org.apache.cassandra.metrics.Histogram;
import org.apache.cassandra.config.DataStorageSpec;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.ArrayClustering;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.codahale.metrics.Timer;
import org.apache.cassandra.metrics.Timer;
import org.apache.cassandra.concurrent.ScheduledExecutorPlus;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.db.ColumnFamilyStore;
Expand Down Expand Up @@ -243,7 +243,7 @@ public void redistributeSummaries() throws IOException
Pair<Long, Map<TableId, LifecycleTransaction>> redistributionTransactionInfo = getRestributionTransactions();
Map<TableId, LifecycleTransaction> transactions = redistributionTransactionInfo.right;
long nonRedistributingOffHeapSize = redistributionTransactionInfo.left;
try (Timer.Context ctx = CompactionManager.instance.getMetrics().indexSummaryRedistributionTime.time())
try (Timer.Context ctx = CompactionManager.instance.getMetrics().indexSummaryRedistributionTime.startTime())
{
redistributeSummaries(new IndexSummaryRedistribution(transactions,
nonRedistributingOffHeapSize,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
import com.google.common.annotations.VisibleForTesting;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.Meter;
import com.codahale.metrics.RatioGauge;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;
Expand Down
68 changes: 68 additions & 0 deletions src/java/org/apache/cassandra/metrics/AtomicLongCounter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* 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.cassandra.metrics;

import java.util.concurrent.atomic.AtomicLong;

import org.apache.cassandra.utils.ReflectionUtils;

/**
* This type of Counter is not very efficient for updates but fast to read.
* It should be used only when getCount performance is critical
* and we can sucrifice the cost to update it by multiple threads
*/
public class AtomicLongCounter extends com.codahale.metrics.Counter implements Counter
{
private final AtomicLong counter = new AtomicLong();

public AtomicLongCounter()
{
ReflectionUtils.setFieldToNull(this, "count");
}

@Override
public void inc()
{
counter.incrementAndGet();
}

@Override
public void inc(long n)
{
counter.addAndGet(n);
}

@Override
public void dec()
{
counter.decrementAndGet();
}

@Override
public void dec(long n)
{
counter.addAndGet(-n);
}

@Override
public long getCount()
{
return counter.get();
}
}
1 change: 0 additions & 1 deletion src/java/org/apache/cassandra/metrics/BatchMetrics.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/
package org.apache.cassandra.metrics;

import com.codahale.metrics.Histogram;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
package org.apache.cassandra.metrics;

import com.codahale.metrics.Gauge;
import com.codahale.metrics.Meter;
import org.apache.cassandra.utils.memory.BufferPool;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
*/
package org.apache.cassandra.metrics;

import com.codahale.metrics.Counter;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
*/
package org.apache.cassandra.metrics;

import com.codahale.metrics.Counter;
import com.codahale.metrics.Histogram;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.codahale.metrics.Counter;
import com.codahale.metrics.Timer;

import static org.apache.cassandra.metrics.CassandraMetricsRegistry.Metrics;

Expand Down
1 change: 0 additions & 1 deletion src/java/org/apache/cassandra/metrics/CQLMetrics.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
*/
package org.apache.cassandra.metrics;

import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.RatioGauge;
import org.apache.cassandra.cql3.QueryProcessor;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,11 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;

import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
import com.codahale.metrics.Histogram;
import com.codahale.metrics.Meter;
import com.codahale.metrics.Metered;
import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.MetricSet;
import com.codahale.metrics.Timer;
import org.apache.cassandra.db.virtual.CollectionVirtualTableAdapter;
import org.apache.cassandra.db.virtual.VirtualTable;
import org.apache.cassandra.db.virtual.model.CounterMetricRow;
Expand Down Expand Up @@ -294,14 +290,39 @@ private static int findNthIndexOf(String str, int start, int n)

public Counter counter(MetricName... name)
{
Counter counter = super.counter(name[0].getMetricName());
String simpleMetricName = name[0].getMetricName();
Metric metric = super.getMetrics().get(simpleMetricName);
if (metric instanceof Counter)
return (Counter) metric;

Counter counter = new ThreadLocalCounter();
super.register(simpleMetricName, counter);
Stream.of(name).forEach(n -> register(n, counter));
return counter;
}

public Counter atomicLongCounter(MetricName... name)
{
String simpleMetricName = name[0].getMetricName();
Metric metric = super.getMetrics().get(simpleMetricName);
if (metric instanceof Counter)
return (Counter) metric;

Counter counter = new AtomicLongCounter();
super.register(simpleMetricName, counter);
Stream.of(name).forEach(n -> register(n, counter));
return counter;
}

public Meter meter(MetricName... name)
{
Meter meter = super.meter(name[0].getMetricName());
String simpleMetricName = name[0].getMetricName();
Metric metric = super.getMetrics().get(simpleMetricName);
if (metric instanceof Meter)
return (Meter) metric;

Meter meter = new ThreadLocalMeter();
super.register(simpleMetricName, meter);
Stream.of(name).forEach(n -> register(n, meter));
return meter;
}
Expand Down
Loading