Skip to content

Commit

Permalink
Merge branch 'master' into amains/build/upgrade_gradle
Browse files Browse the repository at this point in the history
  • Loading branch information
SokolAndrey authored Dec 21, 2023
2 parents eed7f6a + 749c486 commit 3a075fb
Show file tree
Hide file tree
Showing 20 changed files with 648 additions and 131 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle

name: Java CI with Gradle

Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ configurations.archives.artifacts.clear()

allprojects {
group = 'com.uber.m3'
version = '0.11.1'
version = '0.13.0'

apply plugin: 'java'
apply plugin: 'maven'
Expand Down
44 changes: 35 additions & 9 deletions core/benchmark-tests.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,35 @@
Benchmark Mode Cnt Score Error Units
ScopeImplBenchmark.scopeReportingBenchmark thrpt 10 1385.711 ± 55.291 ops/ms
ScopeImplBenchmark.scopeReportingBenchmark:·async thrpt NaN ---
ScopeImplBenchmark.scopeReportingBenchmark:·gc.alloc.rate thrpt 10 ≈ 10⁻⁴ MB/sec
ScopeImplBenchmark.scopeReportingBenchmark:·gc.alloc.rate.norm thrpt 10 ≈ 10⁻⁴ B/op
ScopeImplBenchmark.scopeReportingBenchmark:·gc.count thrpt 10 ≈ 0 counts
ScopeImplBenchmark.scopeReportingBenchmark:·threads.alive thrpt 10 5.800 ± 0.637 threads
ScopeImplBenchmark.scopeReportingBenchmark:·threads.daemon thrpt 10 4.000 ± 0.001 threads
ScopeImplBenchmark.scopeReportingBenchmark:·threads.started thrpt 10 26.000 threads
Benchmark Mode Cnt Score Error Units
ScopeImplBenchmark.scopeReportingBenchmark thrpt 10 1345.606 ± 129.913 ops/ms
ScopeImplBenchmark.scopeReportingBenchmark:·async thrpt NaN ---
ScopeImplBenchmark.scopeReportingBenchmark:·gc.alloc.rate thrpt 10 ≈ 10⁻⁴ MB/sec
ScopeImplBenchmark.scopeReportingBenchmark:·gc.alloc.rate.norm thrpt 10 ≈ 10⁻⁴ B/op
ScopeImplBenchmark.scopeReportingBenchmark:·gc.count thrpt 10 ≈ 0 counts
ScopeImplBenchmark.scopeReportingBenchmark:·threads.alive thrpt 10 5.800 ± 0.637 threads
ScopeImplBenchmark.scopeReportingBenchmark:·threads.daemon thrpt 10 4.000 ± 0.001 threads
ScopeImplBenchmark.scopeReportingBenchmark:·threads.started thrpt 10 26.000 threads
ScopeImplBenchmark.scopeTaggedBenchmark thrpt 10 2440.881 ± 73.028 ops/ms
ScopeImplBenchmark.scopeTaggedBenchmark:·async thrpt NaN ---
ScopeImplBenchmark.scopeTaggedBenchmark:·gc.alloc.rate thrpt 10 1947.506 ± 58.647 MB/sec
ScopeImplBenchmark.scopeTaggedBenchmark:·gc.alloc.rate.norm thrpt 10 880.000 ± 0.001 B/op
ScopeImplBenchmark.scopeTaggedBenchmark:·gc.churn.G1_Eden_Space thrpt 10 1940.575 ± 57.874 MB/sec
ScopeImplBenchmark.scopeTaggedBenchmark:·gc.churn.G1_Eden_Space.norm thrpt 10 876.878 ± 5.246 B/op
ScopeImplBenchmark.scopeTaggedBenchmark:·gc.churn.G1_Old_Gen thrpt 10 0.168 ± 0.001 MB/sec
ScopeImplBenchmark.scopeTaggedBenchmark:·gc.churn.G1_Old_Gen.norm thrpt 10 0.076 ± 0.002 B/op
ScopeImplBenchmark.scopeTaggedBenchmark:·gc.count thrpt 10 1736.000 counts
ScopeImplBenchmark.scopeTaggedBenchmark:·gc.time thrpt 10 1772.000 ms
ScopeImplBenchmark.scopeTaggedBenchmark:·threads.alive thrpt 10 5.800 ± 0.637 threads
ScopeImplBenchmark.scopeTaggedBenchmark:·threads.daemon thrpt 10 4.000 ± 0.001 threads
ScopeImplBenchmark.scopeTaggedBenchmark:·threads.started thrpt 10 26.000 threads
ScopeImplConcurrent.hotkeyLockContention thrpt 10 1.430 ± 0.218 ops/ms
ScopeImplConcurrent.hotkeyLockContention:·async thrpt NaN ---
ScopeImplConcurrent.hotkeyLockContention:·gc.alloc.rate thrpt 10 1244.444 ± 187.772 MB/sec
ScopeImplConcurrent.hotkeyLockContention:·gc.alloc.rate.norm thrpt 10 960144.037 ± 0.011 B/op
ScopeImplConcurrent.hotkeyLockContention:·gc.churn.G1_Eden_Space thrpt 10 1237.763 ± 186.894 MB/sec
ScopeImplConcurrent.hotkeyLockContention:·gc.churn.G1_Eden_Space.norm thrpt 10 954972.637 ± 4468.064 B/op
ScopeImplConcurrent.hotkeyLockContention:·gc.churn.G1_Old_Gen thrpt 10 0.166 ± 0.001 MB/sec
ScopeImplConcurrent.hotkeyLockContention:·gc.churn.G1_Old_Gen.norm thrpt 10 129.528 ± 18.631 B/op
ScopeImplConcurrent.hotkeyLockContention:·gc.count thrpt 10 1564.000 counts
ScopeImplConcurrent.hotkeyLockContention:·gc.time thrpt 10 1336.000 ms
ScopeImplConcurrent.hotkeyLockContention:·threads.alive thrpt 10 5.800 ± 0.637 threads
ScopeImplConcurrent.hotkeyLockContention:·threads.daemon thrpt 10 4.000 ± 0.001 threads
ScopeImplConcurrent.hotkeyLockContention:·threads.started thrpt 10 26.000 threads
29 changes: 20 additions & 9 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
description = 'Interfaces and utilities to report metrics to M3'
apply from: 'jmhFixtures.gradle'

dependencies {
// https://mvnrepository.com/artifact/nl.jqno.equalsverifier/equalsverifier
testImplementation("nl.jqno.equalsverifier:equalsverifier:3.13")
}

sourceSets {
jmh {
java.srcDirs = ['src/jmh/java']
Expand All @@ -42,20 +47,26 @@ task runJmhTests(type: JavaExec, dependsOn: jmhClasses) {
args '-rff', resultFile

// Profile using GC, Threading profilers
args '-prof', 'gc'
args '-prof', 'hs_thr'
if (project.properties.get('busegc', 'true') == 'true') {
args '-prof', 'gc'
args '-prof', 'hs_thr'

// Force GC after every iterations, to make sure that one iteration
// doesn't affect the other one
args '-gc', 'true'
}


// Profile using async-profiling
//
// NOTE: For this to work you need to make sure that async-profiler's library is either
// - Available in LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (Mac)
// - Available in '-Djava.library.path'
// - Explicitly specified with 'async:libPath=</path/libasyncProfiler.so>'
args '-prof', 'async:event=cpu;direction=forward;output=flamegraph'

// Force GC after every iterations, to make sure that one iteration
// doesn't affect the other one
args '-gc', 'true'
// - Explicitly specified in pprof arg, the value 'async:libPath=</path/libasyncProfiler.so>'
args '-prof', project.properties.get('bprof', 'async:event=cpu;direction=forward;output=flamegraph')
args '-bm', project.properties.get('bm', 'thrpt')
args '-t', project.properties.get('bthreads', '1')
args 'com.uber.m3.tally.' + project.properties.get('benchclass', '')
}

classes.finalizedBy(jmhClasses)
classes.finalizedBy(jmhClasses)
3 changes: 3 additions & 0 deletions core/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#bprof=async:event=cpu;direction=forward;output=flamegraph;dir=profile-results;libPath=<path-to-libasyncProfiler.so>
#benchclass=ScopeImplBenchmark.*
#output=benchmark-new.txt
4 changes: 4 additions & 0 deletions core/jmhFixtures.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ dependencies {
jmhFixturesUsageCompile project(project.path)
jmhFixturesCompile('org.openjdk.jmh:jmh-core:1.27')
jmhFixturesCompile('org.openjdk.jmh:jmh-generator-annprocess:1.27')

if (project.gradle.gradleVersion > '5') {
jmhAnnotationProcessor("org.openjdk.jmh:jmh-generator-annprocess:1.27")
}
}
8 changes: 8 additions & 0 deletions core/src/jmh/java/com/uber/m3/tally/ScopeImplBenchmark.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.infra.Blackhole;

import java.util.Random;
import java.util.concurrent.TimeUnit;
Expand All @@ -41,6 +42,8 @@ public class ScopeImplBenchmark {

private static final DurationBuckets EXPONENTIAL_BUCKETS = DurationBuckets.linear(Duration.ofMillis(1), Duration.ofMillis(10), 128);

private static final ImmutableMap<String, String> TAGS_STRING_MAP = ImmutableMap.of("tag1", "value1", "tag2", "value2", "tag3", "value3");

private static final String[] COUNTER_NAMES = {
"first-counter",
"second-counter",
Expand Down Expand Up @@ -70,6 +73,11 @@ public void scopeReportingBenchmark(BenchmarkState state) {
state.scope.reportLoopIteration();
}

@Benchmark
public void scopeTaggedBenchmark(Blackhole blackhole, BenchmarkState state) {
blackhole.consume(state.scope.tagged(TAGS_STRING_MAP));
}

@State(org.openjdk.jmh.annotations.Scope.Benchmark)
public static class BenchmarkState {

Expand Down
75 changes: 75 additions & 0 deletions core/src/jmh/java/com/uber/m3/tally/ScopeImplConcurrent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package com.uber.m3.tally;

import com.uber.m3.util.Duration;
import com.uber.m3.util.ImmutableMap;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(value = 2, jvmArgsAppend = { "-server", "-XX:+UseG1GC" })
public class ScopeImplConcurrent {
private static final List<ScopeKey> SCOPE_KEYS =
Stream.of(" ", "0", "@", "P").map(prefix -> new ScopeKey(prefix, null)).collect(Collectors.toList());

@Benchmark
public void hotkeyLockContention(Blackhole bh, BenchmarkState state) {
ImmutableMap<String, String> common = new ImmutableMap.Builder<String, String>().build();
for (int i = 0; i < 10000; i++) {

for (ScopeKey scopeKey : SCOPE_KEYS) {
Scope scope = state.scope.computeSubscopeIfAbsent("prefix", scopeKey, common);
assert scope != null;
bh.consume(scope);
}
}
}

@State(org.openjdk.jmh.annotations.Scope.Benchmark)
public static class BenchmarkState {

private ScopeImpl scope;

@Setup
public void setup() {
this.scope =
(ScopeImpl) new RootScopeBuilder()
.reporter(new TestStatsReporter())
.reportEvery(Duration.MAX_VALUE);

for (ScopeKey scopeKey : SCOPE_KEYS) {
scope.computeSubscopeIfAbsent("prefix", scopeKey, new ImmutableMap.Builder<String, String>().build());
}
}

@TearDown
public void teardown() {
scope.close();
}
}
}
70 changes: 70 additions & 0 deletions core/src/main/java/com/uber/m3/tally/NullStatsReporter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) 2023 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

package com.uber.m3.tally;

import com.uber.m3.util.Duration;

import java.util.Map;

/**
* NullStatsReporter is a noop implementation of StatsReporter.
*/
public class NullStatsReporter implements StatsReporter {
@Override
public Capabilities capabilities() {
return CapableOf.NONE;
}

@Override
public void flush() {

}

@Override
public void close() {

}

@Override
public void reportCounter(String name, Map<String, String> tags, long value) {

}

@Override
public void reportGauge(String name, Map<String, String> tags, double value) {

}

@Override
public void reportTimer(String name, Map<String, String> tags, Duration interval) {

}

@Override
public void reportHistogramValueSamples(String name, Map<String, String> tags, Buckets buckets, double bucketLowerBound, double bucketUpperBound, long samples) {

}

@Override
public void reportHistogramDurationSamples(String name, Map<String, String> tags, Buckets buckets, Duration bucketLowerBound, Duration bucketUpperBound, long samples) {

}
}
Loading

0 comments on commit 3a075fb

Please sign in to comment.