diff --git a/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/RecordBatchedBenchmark.java b/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/RecordBatchedBenchmark.java new file mode 100644 index 0000000000..db24ab7db1 --- /dev/null +++ b/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/RecordBatchedBenchmark.java @@ -0,0 +1,170 @@ +/* + * Copyright 2019, OpenCensus Authors + * + * Licensed 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 io.opencensus.benchmarks.stats; + +import io.opencensus.benchmarks.tags.TagsBenchmarksUtil; +import io.opencensus.stats.MeasureMap; +import io.opencensus.stats.StatsRecorder; +import io.opencensus.stats.ViewManager; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.Tagger; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +/** Benchmarks for {@link io.opencensus.stats.StatsRecorder}. */ +public class RecordBatchedBenchmark { + @State(org.openjdk.jmh.annotations.Scope.Benchmark) + public static class Data { + @Param({"0", "1", "2", "3", "6", "8"}) + int numValues; + + @Param({"impl", "impl-lite"}) + String implementation; + + private StatsRecorder recorder; + private Tagger tagger; + private TagContext tags; + + @Setup + public void setup() throws Exception { + ViewManager manager = StatsBenchmarksUtil.getViewManager(implementation); + recorder = StatsBenchmarksUtil.getStatsRecorder(implementation); + tagger = TagsBenchmarksUtil.getTagger(implementation); + tags = TagsBenchmarksUtil.createTagContext(tagger.emptyBuilder(), 1); + for (int i = 0; i < numValues; i++) { + manager.registerView(StatsBenchmarksUtil.DOUBLE_COUNT_VIEWS[i]); + manager.registerView(StatsBenchmarksUtil.LONG_COUNT_VIEWS[i]); + manager.registerView(StatsBenchmarksUtil.DOUBLE_SUM_VIEWS[i]); + manager.registerView(StatsBenchmarksUtil.LONG_SUM_VIEWS[i]); + manager.registerView(StatsBenchmarksUtil.DOUBLE_DISTRIBUTION_VIEWS[i]); + manager.registerView(StatsBenchmarksUtil.LONG_DISTRIBUTION_VIEWS[i]); + manager.registerView(StatsBenchmarksUtil.DOUBLE_LASTVALUE_VIEWS[i]); + manager.registerView(StatsBenchmarksUtil.LONG_LASTVALUE_VIEWS[i]); + } + } + } + + /** Record batched double count measures. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordBatchedDoubleCount(Data data) { + MeasureMap map = data.recorder.newMeasureMap(); + for (int i = 0; i < data.numValues; i++) { + map.put(StatsBenchmarksUtil.DOUBLE_COUNT_MEASURES[i], (double) i); + } + map.record(data.tags); + return map; + } + + /** Record batched long count measures. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordBatchedLongCount(Data data) { + MeasureMap map = data.recorder.newMeasureMap(); + for (int i = 0; i < data.numValues; i++) { + map.put(StatsBenchmarksUtil.LONG_COUNT_MEASURES[i], i); + } + map.record(data.tags); + return map; + } + + /** Record batched double sum measures. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordBatchedDoubleSum(Data data) { + MeasureMap map = data.recorder.newMeasureMap(); + for (int i = 0; i < data.numValues; i++) { + map.put(StatsBenchmarksUtil.DOUBLE_SUM_MEASURES[i], (double) i); + } + map.record(data.tags); + return map; + } + + /** Record batched long sum measures. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordBatchedLongSum(Data data) { + MeasureMap map = data.recorder.newMeasureMap(); + for (int i = 0; i < data.numValues; i++) { + map.put(StatsBenchmarksUtil.LONG_SUM_MEASURES[i], i); + } + map.record(data.tags); + return map; + } + + /** Record batched double distribution measures. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordBatchedDoubleDistribution(Data data) { + MeasureMap map = data.recorder.newMeasureMap(); + for (int i = 0; i < data.numValues; i++) { + map.put(StatsBenchmarksUtil.DOUBLE_DISTRIBUTION_MEASURES[i], (double) i); + } + map.record(data.tags); + return map; + } + + /** Record batched ling distribution measures. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordBatchedLongDistribution(Data data) { + MeasureMap map = data.recorder.newMeasureMap(); + for (int i = 0; i < data.numValues; i++) { + map.put(StatsBenchmarksUtil.DOUBLE_DISTRIBUTION_MEASURES[i], i); + } + map.record(data.tags); + return map; + } + + /** Record batched double last value measures. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordBatchedDoubleLastValue(Data data) { + MeasureMap map = data.recorder.newMeasureMap(); + for (int i = 0; i < data.numValues; i++) { + map.put(StatsBenchmarksUtil.DOUBLE_LASTVALUE_MEASURES[i], (double) i); + } + map.record(data.tags); + return map; + } + + /** Record batched long last value measures. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordBatchedLongLastValue(Data data) { + MeasureMap map = data.recorder.newMeasureMap(); + for (int i = 0; i < data.numValues; i++) { + map.put(StatsBenchmarksUtil.LONG_LASTVALUE_MEASURES[i], i); + } + map.record(data.tags); + return map; + } +} diff --git a/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/RecordDifferentTagValuesBenchmark.java b/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/RecordDifferentTagValuesBenchmark.java new file mode 100644 index 0000000000..947a8a6e90 --- /dev/null +++ b/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/RecordDifferentTagValuesBenchmark.java @@ -0,0 +1,158 @@ +/* + * Copyright 2019, OpenCensus Authors + * + * Licensed 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 io.opencensus.benchmarks.stats; + +import io.opencensus.benchmarks.tags.TagsBenchmarksUtil; +import io.opencensus.stats.Measure; +import io.opencensus.stats.MeasureMap; +import io.opencensus.stats.StatsRecorder; +import io.opencensus.stats.ViewManager; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.Tagger; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +/** Benchmarks for {@link io.opencensus.trace.Tagger}. */ +public class RecordDifferentTagValuesBenchmark { + @State(org.openjdk.jmh.annotations.Scope.Benchmark) + public static class Data { + @Param({"0", "1", "2", "3", "6", "8"}) + int numTags; + + @Param({"impl", "impl-lite"}) + String implementation; + + private StatsRecorder recorder; + private ViewManager manager; + private Tagger tagger; + private List contexts; + + @Setup + public void setup() throws Exception { + manager = StatsBenchmarksUtil.getViewManager(implementation); + recorder = StatsBenchmarksUtil.getStatsRecorder(implementation); + tagger = TagsBenchmarksUtil.getTagger(implementation); + contexts = createContexts(numTags); + manager.registerView(StatsBenchmarksUtil.DOUBLE_COUNT_VIEWS[0]); + manager.registerView(StatsBenchmarksUtil.LONG_COUNT_VIEWS[0]); + manager.registerView(StatsBenchmarksUtil.DOUBLE_SUM_VIEWS[0]); + manager.registerView(StatsBenchmarksUtil.LONG_SUM_VIEWS[0]); + manager.registerView(StatsBenchmarksUtil.DOUBLE_DISTRIBUTION_VIEWS[0]); + manager.registerView(StatsBenchmarksUtil.LONG_DISTRIBUTION_VIEWS[0]); + manager.registerView(StatsBenchmarksUtil.DOUBLE_LASTVALUE_VIEWS[0]); + manager.registerView(StatsBenchmarksUtil.LONG_LASTVALUE_VIEWS[0]); + } + + // creates 'size' tag contexts mapping "key0" -> "valueN" + private List createContexts(int size) { + TagContext[] contexts = new TagContext[size]; + for (int i = 0; i < size; i++) { + contexts[i] = + tagger + .emptyBuilder() + .put( + TagsBenchmarksUtil.TAG_KEYS.get(0), + TagsBenchmarksUtil.TAG_VALUES.get(i), + TagsBenchmarksUtil.UNLIMITED_PROPAGATION) + .build(); + } + return Arrays.asList(contexts); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordDoubleCount(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_COUNT_MEASURES[0], (double) 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordLongCount(Data data) { + return record(data, StatsBenchmarksUtil.LONG_COUNT_MEASURES[0], 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordDoubleSum(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_SUM_MEASURES[0], (double) 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordLongSum(Data data) { + return record(data, StatsBenchmarksUtil.LONG_SUM_MEASURES[0], 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordDoubleDistribution(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_DISTRIBUTION_MEASURES[0], (double) 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordLongDistribution(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_DISTRIBUTION_MEASURES[0], 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordDoubleLastValue(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_LASTVALUE_MEASURES[0], (double) 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordLongLastValue(Data data) { + return record(data, StatsBenchmarksUtil.LONG_LASTVALUE_MEASURES[0], 11); + } + + private static MeasureMap record(Data data, Measure.MeasureLong measure, int value) { + MeasureMap map = data.recorder.newMeasureMap(); + map.put(measure, value); + for (TagContext tags : data.contexts) { + map.record(tags); + } + return map; + } + + private static MeasureMap record(Data data, Measure.MeasureDouble measure, double value) { + MeasureMap map = data.recorder.newMeasureMap(); + map.put(measure, value); + for (TagContext tags : data.contexts) { + map.record(tags); + } + return map; + } +} diff --git a/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/RecordMultipleViewsBenchmark.java b/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/RecordMultipleViewsBenchmark.java new file mode 100644 index 0000000000..1345a8b063 --- /dev/null +++ b/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/RecordMultipleViewsBenchmark.java @@ -0,0 +1,194 @@ +/* + * Copyright 2019, OpenCensus Authors + * + * Licensed 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 io.opencensus.benchmarks.stats; + +import io.opencensus.benchmarks.tags.TagsBenchmarksUtil; +import io.opencensus.stats.Aggregation; +import io.opencensus.stats.Measure; +import io.opencensus.stats.MeasureMap; +import io.opencensus.stats.StatsRecorder; +import io.opencensus.stats.ViewManager; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.TagContextBuilder; +import io.opencensus.tags.Tagger; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +/** Benchmarks for {@link io.opencensus.trace.Tagger}. */ +public class RecordMultipleViewsBenchmark { + @State(org.openjdk.jmh.annotations.Scope.Benchmark) + public static class Data { + @Param({"0", "1", "2", "3", "6", "8"}) + int numViews; + + @Param({"impl", "impl-lite"}) + String implementation; + + private StatsRecorder recorder; + private Tagger tagger; + private TagContext tagContext; + + @Setup + public void setup() throws Exception { + ViewManager manager = StatsBenchmarksUtil.getViewManager(implementation); + recorder = StatsBenchmarksUtil.getStatsRecorder(implementation); + tagger = TagsBenchmarksUtil.getTagger(implementation); + tagContext = createContext(numViews); + + for (int i = 0; i < numViews; i++) { + // count + manager.registerView( + StatsBenchmarksUtil.createView( + "DC" + i, + StatsBenchmarksUtil.DOUBLE_COUNT_MEASURES[0], + Aggregation.Count.create(), + TagsBenchmarksUtil.TAG_KEYS.get(i))); + manager.registerView( + StatsBenchmarksUtil.createView( + "LC" + i, + StatsBenchmarksUtil.LONG_COUNT_MEASURES[0], + Aggregation.Count.create(), + TagsBenchmarksUtil.TAG_KEYS.get(i))); + // sum + manager.registerView( + StatsBenchmarksUtil.createView( + "DS" + i, + StatsBenchmarksUtil.DOUBLE_SUM_MEASURES[0], + Aggregation.Sum.create(), + TagsBenchmarksUtil.TAG_KEYS.get(i))); + manager.registerView( + StatsBenchmarksUtil.createView( + "LS" + i, + StatsBenchmarksUtil.LONG_SUM_MEASURES[0], + Aggregation.Sum.create(), + TagsBenchmarksUtil.TAG_KEYS.get(i))); + // distribution + manager.registerView( + StatsBenchmarksUtil.createView( + "DD" + i, + StatsBenchmarksUtil.DOUBLE_DISTRIBUTION_MEASURES[0], + StatsBenchmarksUtil.DISTRIBUTION, + TagsBenchmarksUtil.TAG_KEYS.get(i))); + manager.registerView( + StatsBenchmarksUtil.createView( + "LD" + i, + StatsBenchmarksUtil.LONG_DISTRIBUTION_MEASURES[0], + StatsBenchmarksUtil.DISTRIBUTION, + TagsBenchmarksUtil.TAG_KEYS.get(i))); + // last value + manager.registerView( + StatsBenchmarksUtil.createView( + "DL" + i, + StatsBenchmarksUtil.DOUBLE_LASTVALUE_MEASURES[0], + Aggregation.LastValue.create(), + TagsBenchmarksUtil.TAG_KEYS.get(i))); + manager.registerView( + StatsBenchmarksUtil.createView( + "LL" + i, + StatsBenchmarksUtil.LONG_LASTVALUE_MEASURES[0], + Aggregation.LastValue.create(), + TagsBenchmarksUtil.TAG_KEYS.get(i))); + } + } + + // creates tag context with n tags mapping "keyN" -> "value0" + private TagContext createContext(int size) { + TagContextBuilder builder = tagger.emptyBuilder(); + for (int i = 0; i < size; i++) { + builder.put( + TagsBenchmarksUtil.TAG_KEYS.get(i), + TagsBenchmarksUtil.TAG_VALUES.get(0), + TagsBenchmarksUtil.UNLIMITED_PROPAGATION); + } + return builder.build(); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordDoubleCount(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_COUNT_MEASURES[0], (double) 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordLongCount(Data data) { + return record(data, StatsBenchmarksUtil.LONG_COUNT_MEASURES[0], 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordDoubleSum(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_SUM_MEASURES[0], (double) 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordLongSum(Data data) { + return record(data, StatsBenchmarksUtil.LONG_SUM_MEASURES[0], 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordDoubleDistribution(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_DISTRIBUTION_MEASURES[0], (double) 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordLongDistribution(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_DISTRIBUTION_MEASURES[0], 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordDoubleLastValue(Data data) { + return record(data, StatsBenchmarksUtil.DOUBLE_LASTVALUE_MEASURES[0], (double) 11); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public MeasureMap recordLongLastValue(Data data) { + return record(data, StatsBenchmarksUtil.LONG_LASTVALUE_MEASURES[0], 11); + } + + private static MeasureMap record(Data data, Measure.MeasureLong measure, int value) { + MeasureMap map = data.recorder.newMeasureMap(); + map.put(measure, value).record(data.tagContext); + return map; + } + + private static MeasureMap record(Data data, Measure.MeasureDouble measure, double value) { + MeasureMap map = data.recorder.newMeasureMap(); + map.put(measure, value).record(data.tagContext); + return map; + } +} diff --git a/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/StatsBenchmarksUtil.java b/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/StatsBenchmarksUtil.java new file mode 100644 index 0000000000..ee0c52fac3 --- /dev/null +++ b/benchmarks/src/jmh/java/io/opencensus/benchmarks/stats/StatsBenchmarksUtil.java @@ -0,0 +1,141 @@ +/* + * Copyright 2019, OpenCensus Authors + * + * Licensed 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 io.opencensus.benchmarks.stats; + +import static io.opencensus.benchmarks.tags.TagsBenchmarksUtil.TAG_KEYS; + +import io.opencensus.impl.stats.StatsComponentImpl; +import io.opencensus.impllite.stats.StatsComponentImplLite; +import io.opencensus.stats.Aggregation; +import io.opencensus.stats.BucketBoundaries; +import io.opencensus.stats.Measure; +import io.opencensus.stats.StatsRecorder; +import io.opencensus.stats.View; +import io.opencensus.stats.ViewManager; +import io.opencensus.tags.TagKey; +import java.util.Arrays; + +/** Util class for Benchmarks. */ +final class StatsBenchmarksUtil { + private static final StatsComponentImpl statsComponentImpl = new StatsComponentImpl(); + private static final StatsComponentImplLite statsComponentImplLite = new StatsComponentImplLite(); + + private static final int MEASURES = 8; + private static final int VIEWS = 8; + + static final Aggregation.Distribution DISTRIBUTION = + Aggregation.Distribution.create( + BucketBoundaries.create(Arrays.asList(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0))); + + static final Measure.MeasureDouble[] DOUBLE_COUNT_MEASURES = + createMeasureDoubles(MEASURES, "Count"); + static final Measure.MeasureLong[] LONG_COUNT_MEASURES = createMeasureLongs(MEASURES, "Count"); + + static final Measure.MeasureDouble[] DOUBLE_SUM_MEASURES = createMeasureDoubles(MEASURES, "Sum"); + static final Measure.MeasureLong[] LONG_SUM_MEASURES = createMeasureLongs(MEASURES, "Sum"); + + static final Measure.MeasureDouble[] DOUBLE_DISTRIBUTION_MEASURES = + createMeasureDoubles(MEASURES, "Distribution"); + static final Measure.MeasureLong[] LONG_DISTRIBUTION_MEASURES = + createMeasureLongs(MEASURES, "Distribution"); + + static final Measure.MeasureDouble[] DOUBLE_LASTVALUE_MEASURES = + createMeasureDoubles(MEASURES, "LastValue"); + static final Measure.MeasureLong[] LONG_LASTVALUE_MEASURES = + createMeasureLongs(MEASURES, "LastValue"); + + static final View[] DOUBLE_COUNT_VIEWS = + createViews(VIEWS, DOUBLE_COUNT_MEASURES, Aggregation.Count.create(), TAG_KEYS.get(0)); + static final View[] LONG_COUNT_VIEWS = + createViews(VIEWS, LONG_COUNT_MEASURES, Aggregation.Count.create(), TAG_KEYS.get(0)); + + static final View[] DOUBLE_SUM_VIEWS = + createViews(VIEWS, DOUBLE_SUM_MEASURES, Aggregation.Sum.create(), TAG_KEYS.get(0)); + static final View[] LONG_SUM_VIEWS = + createViews(VIEWS, LONG_SUM_MEASURES, Aggregation.Sum.create(), TAG_KEYS.get(0)); + + static final View[] DOUBLE_DISTRIBUTION_VIEWS = + createViews(VIEWS, DOUBLE_DISTRIBUTION_MEASURES, DISTRIBUTION, TAG_KEYS.get(0)); + static final View[] LONG_DISTRIBUTION_VIEWS = + createViews(VIEWS, LONG_DISTRIBUTION_MEASURES, DISTRIBUTION, TAG_KEYS.get(0)); + + static final View[] DOUBLE_LASTVALUE_VIEWS = + createViews( + VIEWS, DOUBLE_LASTVALUE_MEASURES, Aggregation.LastValue.create(), TAG_KEYS.get(0)); + static final View[] LONG_LASTVALUE_VIEWS = + createViews(VIEWS, LONG_LASTVALUE_MEASURES, Aggregation.LastValue.create(), TAG_KEYS.get(0)); + + static StatsRecorder getStatsRecorder(String implementation) { + if (implementation.equals("impl")) { + // We can return the global tracer here because if impl is linked the global tracer will be + // the impl one. + // TODO(bdrutu): Make everything not be a singleton (disruptor, etc.) and use a new + // TraceComponentImpl similar to TraceComponentImplLite. + return statsComponentImpl.getStatsRecorder(); + } else if (implementation.equals("impl-lite")) { + return statsComponentImplLite.getStatsRecorder(); + } else { + throw new RuntimeException("Invalid stats recorder implementation specified."); + } + } + + static ViewManager getViewManager(String implementation) { + if (implementation.equals("impl")) { + // We can return the global tracer here because if impl is linked the global tracer will be + // the impl one. + // TODO(bdrutu): Make everything not be a singleton (disruptor, etc.) and use a new + // TraceComponentImpl similar to TraceComponentImplLite. + return statsComponentImpl.getViewManager(); + } else if (implementation.equals("impl-lite")) { + return statsComponentImplLite.getViewManager(); + } else { + throw new RuntimeException("Invalid view manager implementation specified."); + } + } + + private static View[] createViews( + int size, Measure[] measures, Aggregation aggregation, TagKey... keys) { + View[] views = new View[size]; + for (int i = 0; i < size; i++) { + views[i] = createView(measures[i].getName(), measures[i], aggregation, keys); + } + return views; + } + + static View createView(String name, Measure measure, Aggregation aggregation, TagKey... keys) { + return View.create(View.Name.create(name), "", measure, aggregation, Arrays.asList(keys)); + } + + private static Measure.MeasureDouble[] createMeasureDoubles(int size, String name) { + Measure.MeasureDouble[] measures = new Measure.MeasureDouble[size]; + for (int i = 0; i < size; i++) { + measures[i] = Measure.MeasureDouble.create(name + "_MD" + i, "", "ns"); + } + return measures; + } + + private static Measure.MeasureLong[] createMeasureLongs(int size, String name) { + Measure.MeasureLong[] measures = new Measure.MeasureLong[size]; + for (int i = 0; i < size; i++) { + measures[i] = Measure.MeasureLong.create(name + "_ML" + i, "", "ns"); + } + return measures; + } + + // Avoid instances of this class. + private StatsBenchmarksUtil() {} +} diff --git a/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/NestedTagContextCreationBenchmark.java b/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/NestedTagContextCreationBenchmark.java new file mode 100644 index 0000000000..cfe5df03b2 --- /dev/null +++ b/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/NestedTagContextCreationBenchmark.java @@ -0,0 +1,62 @@ +/* + * Copyright 2019, OpenCensus Authors + * + * Licensed 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 io.opencensus.benchmarks.tags; + +import io.opencensus.tags.TagContext; +import io.opencensus.tags.Tagger; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +/** Benchmarks for {@link io.opencensus.trace.TagContextBuilder}. */ +public class NestedTagContextCreationBenchmark { + + @State(org.openjdk.jmh.annotations.Scope.Benchmark) + public static class Data { + private Tagger tagger; + private TagContext baseTagContext; + + @Param({"impl", "impl-lite"}) + String implementation; + + @Param({"0", "1", "2", "4", "8", "16"}) + int numTags; + + @Param({"0", "1", "2", "4", "8", "16"}) + int numBaseTags; + + @Setup + public void setup() { + tagger = TagsBenchmarksUtil.getTagger(implementation); + baseTagContext = TagsBenchmarksUtil.createTagContext(tagger.emptyBuilder(), numBaseTags); + } + } + + /** Build nested tag context. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public TagContext timeNestedTagContext(Data data) { + return TagsBenchmarksUtil.createTagContext( + data.tagger.toBuilder(data.baseTagContext), data.numTags); + } +} diff --git a/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/TagContextBenchmark.java b/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/TagContextBenchmark.java new file mode 100644 index 0000000000..382b705197 --- /dev/null +++ b/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/TagContextBenchmark.java @@ -0,0 +1,104 @@ +/* + * Copyright 2019, OpenCensus Authors + * + * Licensed 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 io.opencensus.benchmarks.tags; + +import io.opencensus.common.Scope; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.Tagger; +import io.opencensus.tags.propagation.TagContextBinarySerializer; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; + +/** Benchmarks for {@link io.opencensus.trace.Tagger}. */ +public class TagContextBenchmark { + @State(org.openjdk.jmh.annotations.Scope.Benchmark) + public static class Data { + @Param({"0", "1", "2", "4", "8", "16"}) + int numTags; + + @Param({"impl", "impl-lite"}) + String implementation; + + private Scope scope; + private Tagger tagger; + private TagContextBinarySerializer serializer; + private TagContext tagContext; + private byte[] serializedTagContext; + + @Setup + public void setup() throws Exception { + tagger = TagsBenchmarksUtil.getTagger(implementation); + serializer = TagsBenchmarksUtil.getTagContextBinarySerializer(implementation); + tagContext = TagsBenchmarksUtil.createTagContext(tagger.emptyBuilder(), numTags); + scope = tagger.withTagContext(tagContext); + serializedTagContext = serializer.toByteArray(tagContext); + } + + @TearDown + public void tearDown() { + scope.close(); + } + } + + /** Create a tag context. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public TagContext tagContextCreation(Data data) { + return TagsBenchmarksUtil.createTagContext(data.tagger.emptyBuilder(), data.numTags); + } + + /** Open and close a tag context scope. */ + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public Scope scopeTagContext(Data data) { + Scope scope = data.tagger.withTagContext(data.tagContext); + scope.close(); + return scope; + } + + /** Get the current tag context. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public TagContext getCurrentTagContext(Data data) { + return data.tagger.getCurrentTagContext(); + } + + /** Serialize a tag context. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public byte[] serializeTagContext(Data data) throws Exception { + return data.serializer.toByteArray(data.tagContext); + } + + /** Deserialize a tag context. */ + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public TagContext deserializeTagContext(Data data) throws Exception { + return data.serializer.fromByteArray(data.serializedTagContext); + } +} diff --git a/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/TagsBenchmark.java b/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/TagsBenchmark.java new file mode 100644 index 0000000000..29d73d27d0 --- /dev/null +++ b/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/TagsBenchmark.java @@ -0,0 +1,78 @@ +/* + * Copyright 2019, OpenCensus Authors + * + * Licensed 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 io.opencensus.benchmarks.tags; + +import io.opencensus.tags.Tag; +import io.opencensus.tags.TagKey; +import io.opencensus.tags.TagValue; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +/** Benchmarks for {@link io.opencensus.trace.Tagger}. */ +public class TagsBenchmark { + @State(org.openjdk.jmh.annotations.Scope.Benchmark) + public static class Data { + @Param({"impl", "impl-lite"}) + String implementation; + + @Param({"1", "8", "32", "128", "255"}) + int size; + + private String input; + private TagKey tagKey; + private TagValue tagValue; + + @Setup + public void setup() throws Exception { + StringBuilder builder = new StringBuilder(size); + // build a string with characters from 'a' to 'z' + for (int i = 0; i < size; i++) { + builder.append((char) (97 + i % 26)); + } + input = builder.toString(); + tagKey = TagKey.create(input); + tagValue = TagValue.create(input); + } + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public TagKey tagKeyCreation(Data data) { + return TagKey.create("key"); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public TagValue tagValueCreation(Data data) { + return TagValue.create("val"); + } + + @Benchmark + @BenchmarkMode(Mode.AverageTime) + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public Tag tagCreation(Data data) { + return Tag.create(data.tagKey, data.tagValue, TagsBenchmarksUtil.UNLIMITED_PROPAGATION); + } +} diff --git a/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/TagsBenchmarksUtil.java b/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/TagsBenchmarksUtil.java new file mode 100644 index 0000000000..3ed54adc60 --- /dev/null +++ b/benchmarks/src/jmh/java/io/opencensus/benchmarks/tags/TagsBenchmarksUtil.java @@ -0,0 +1,108 @@ +/* + * Copyright 2019, OpenCensus Authors + * + * Licensed 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 io.opencensus.benchmarks.tags; + +import com.google.common.annotations.VisibleForTesting; +import io.opencensus.implcore.tags.TagsComponentImplBase; +import io.opencensus.impllite.tags.TagsComponentImplLite; +import io.opencensus.tags.TagContext; +import io.opencensus.tags.TagContextBuilder; +import io.opencensus.tags.TagKey; +import io.opencensus.tags.TagMetadata; +import io.opencensus.tags.TagValue; +import io.opencensus.tags.Tagger; +import io.opencensus.tags.propagation.TagContextBinarySerializer; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** Util class for Tags Benchmarks. */ +public final class TagsBenchmarksUtil { + private static final TagsComponentImplBase tagsComponentImplBase = new TagsComponentImplBase(); + private static final TagsComponentImplLite tagsComponentImplLite = new TagsComponentImplLite(); + + public static final List TAG_KEYS = + Collections.unmodifiableList(Arrays.asList(createTagKeys(16, "key"))); + public static final List TAG_VALUES = + Collections.unmodifiableList(Arrays.asList(createTagValues(16, "val"))); + public static final TagMetadata UNLIMITED_PROPAGATION = + TagMetadata.create(TagMetadata.TagTtl.UNLIMITED_PROPAGATION); + + /** Gets the {@link Tagger} for the specified 'implementation'. */ + @VisibleForTesting + public static Tagger getTagger(String implementation) { + if (implementation.equals("impl")) { + // We can return the global tracer here because if impl is linked the global tracer will be + // the impl one. + // TODO(bdrutu): Make everything not be a singleton (disruptor, etc.) and use a new + // TraceComponentImpl similar to TraceComponentImplLite. + return tagsComponentImplBase.getTagger(); + } else if (implementation.equals("impl-lite")) { + return tagsComponentImplLite.getTagger(); + } else { + throw new RuntimeException("Invalid tagger implementation specified."); + } + } + + /** Gets the {@link TagContextBinarySerializer} for the specified 'implementation'. */ + @VisibleForTesting + public static TagContextBinarySerializer getTagContextBinarySerializer(String implementation) { + if (implementation.equals("impl")) { + // We can return the global tracer here because if impl is linked the global tracer will be + // the impl one. + // TODO(bdrutu): Make everything not be a singleton (disruptor, etc.) and use a new + // TraceComponentImpl similar to TraceComponentImplLite. + return tagsComponentImplBase.getTagPropagationComponent().getBinarySerializer(); + } else if (implementation.equals("impl-lite")) { + return tagsComponentImplLite.getTagPropagationComponent().getBinarySerializer(); + } else { + throw new RuntimeException("Invalid binary serializer implementation specified."); + } + } + + /** Creates an array of TagKeys of 'size' with 'name' prefix. */ + @VisibleForTesting + public static TagKey[] createTagKeys(int size, String name) { + TagKey[] keys = new TagKey[size]; + for (int i = 0; i < size; i++) { + keys[i] = TagKey.create(name + i); + } + return keys; + } + + /** Creates an array of TagValues of 'size' with 'name' prefix. */ + @VisibleForTesting + public static TagValue[] createTagValues(int size, String name) { + TagValue[] values = new TagValue[size]; + for (int i = 0; i < size; i++) { + values[i] = TagValue.create(name + i); + } + return values; + } + + /** Adds 'numTags' tags to 'tagsBuilder' and returns the associated tag context. */ + @VisibleForTesting + public static TagContext createTagContext(TagContextBuilder tagsBuilder, int numTags) { + for (int i = 0; i < numTags; i++) { + tagsBuilder.put(TAG_KEYS.get(i), TAG_VALUES.get(i), UNLIMITED_PROPAGATION); + } + return tagsBuilder.build(); + } + + // Avoid instances of this class. + private TagsBenchmarksUtil() {} +}