-
Notifications
You must be signed in to change notification settings - Fork 696
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
SOLR-15428: Integrate the OpenJDK JMH micro benchmark framework for m… #214
Conversation
fd9a36a
to
16b22d2
Compare
solr/test-framework/src/java/org/apache/solr/util/RandomizeSSL.java
Outdated
Show resolved
Hide resolved
611102e
to
9297745
Compare
Can you add a task for |
6b7735b
to
24b086f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a review but have yet to try this, which I am anxious to do.
It seems there is an overarching issue relating to the benchmark running classes in test-framework yet not having a RandomizedTesting unit test runner and thus no random seed? Let's ping Dawid about this use-case; ehh? It'd be nice to explicitly initialize that framework without using the runner.
solr/test-framework/src/java/org/apache/solr/util/RandomizeSSL.java
Outdated
Show resolved
Hide resolved
solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
Outdated
Show resolved
Hide resolved
solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudTestCase.java
Outdated
Show resolved
Hide resolved
solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java
Show resolved
Hide resolved
solr/test-framework/src/jmh/org/apache/solr/bench/DocMakerRamGen.java
Outdated
Show resolved
Hide resolved
solr/test-framework/src/jmh/org/apache/solr/bench/DocMakerRamGen.java
Outdated
Show resolved
Hide resolved
solr/test-framework/src/jmh/org/apache/solr/bench/DocMakerRamGen.java
Outdated
Show resolved
Hide resolved
solr/test-framework/src/jmh/org/apache/solr/bench/FieldDef.java
Outdated
Show resolved
Hide resolved
solr/test-framework/src/jmh/org/apache/solr/bench/FieldDef.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this capability embedded into the test-framework module instead of being a new module because we want to publish the foundation so other modules (including 3rd party) can use them? test-framework is about publishing utilities for other modules, so that's the only reason I can think of why this was added there. Otherwise, it seems a new module would be more appropriate.
bq. Otherwise, it seems a new module would be more appropriate. You don't back up that statement with any support, other than: bq. test-framework is about publishing utilities for other modules Which I'm not sure I agree with. Initially, I will say its here for:
I like to stack up reasons for going one way or another, but I see the test-framework module as the home of the testing framework, not "about publishing utilities for other modules", so not really adding to my calculus in that form. I also thought there would be more that was shared initially though. And I've sense realized this could use more separation from the randomized testing framework layers and requirements, and the different needs do make reuse of items between benchmark and junit tests a bit less simple and with more of a need to make sure mini clusters and jettyrunners are happy outside of randomized runner stuff. |
24b086f
to
18f041f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the move to its own module! It'll be nice to see them all easily as we learn to explore this capability -- it's more discoverable. It also appears to fit in better from a build/Gradle perspective than when it was embedded in solr-test-framework.
Validate.isTrue(endExclusive >= startInclusive, | ||
"Start value must be smaller or equal to end value."); | ||
Validate.isTrue(startInclusive >= 0, "Both range values must be non-negative."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can use Objects.checkIndex
for this
solr/benchmark/build.gradle
Outdated
args '-jvmArgsPrepend', '-Dlog4j2.is.webapp=false' | ||
args '-jvmArgsPrepend', '-Dlog4j2.garbagefreeThreadContextMap=true' | ||
args '-jvmArgsPrepend', '-Dlog4j2.enableDirectEncoders=true' | ||
args '-jvmArgsPrepend', '-Dlog4j2.enable.threadlocals=true' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can these make their way into our standard deployment as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://issues.apache.org/jira/browse/SOLR-15477 Coming soon.
1ba7f6c
to
eb9339d
Compare
|
||
echo "gradle build done" | ||
|
||
echo "running JMH with args: $@" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ShellCheck: Argument mixes string and array. Use * or separate argument.
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
0e96672
to
d4974fd
Compare
|
||
// dump Solr metrics | ||
Path metricsResults = | ||
Paths.get( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PATH_TRAVERSAL_IN: This API (java/nio/file/Paths.get(Ljava/lang/String;[Ljava/lang/String;)Ljava/nio/file/Path;) reads a file whose location might be specified by user input (details)
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
Set<String> registryNames = metricsManager.registryNames(); | ||
for (String registryName : registryNames) { | ||
MetricRegistry metricsRegisty = metricsManager.registry(registryName); | ||
try (PrintStream ps = outputDirectory == null ? new NullPrintStream() : new PrintStream(new File(outputDirectory, registryName + "_" + fileName), StandardCharsets.UTF_8)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PATH_TRAVERSAL_IN: This API (java/io/File.(Ljava/io/File;Ljava/lang/String;)V) reads a file whose location might be specified by user input (details)
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
SplittableRandom random = new SplittableRandom(seed); | ||
if (fieldDef.getLength() > -1) { | ||
return RandomStringUtils.random( | ||
nextInt(fieldDef.getLength(), fieldDef.getLength(), random), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PREDICTABLE_RANDOM: This random generator (java.util.Random) is predictable (details)
(at-me in a reply with help
or ignore
)
ThreadLocalRandom.current(), fieldDef.getLength(), fieldDef.getLength()); | ||
} else { | ||
return TestUtil.randomRealisticUnicodeString( | ||
ThreadLocalRandom.current(), 1, fieldDef.getMaxLength()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PREDICTABLE_RANDOM: This random generator (java.util.concurrent.ThreadLocalRandom) is predictable (details)
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
} | ||
this.maxCardinality = maxCardinality; | ||
this.cardinalityStart = | ||
ThreadLocalRandom.current().nextLong(0, Long.MAX_VALUE - maxCardinality); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PREDICTABLE_RANDOM: This random generator (java.util.concurrent.ThreadLocalRandom) is predictable (details)
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
} | ||
|
||
// set the seed used by ThreadLocalRandom | ||
System.setProperty("randomSeed", Long.toString(new Random(seed).nextLong())); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PREDICTABLE_RANDOM: This random generator (java.util.Random) is predictable (details)
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
|
||
QueryRequest queryRequest = new QueryRequest(new SolrQuery("q", "*:*", "rows", "1")); | ||
queryRequest.setBasePath( | ||
nodes.get(ThreadLocalRandom.current().nextInt(cluster.getJettySolrRunners().size()))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PREDICTABLE_RANDOM: This random generator (java.util.concurrent.ThreadLocalRandom) is predictable (details)
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
throws Exception { | ||
UpdateRequest updateRequest = new UpdateRequest(); | ||
updateRequest.setBasePath( | ||
miniClusterState.nodes.get(ThreadLocalRandom.current().nextInt(state.nodeCount))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PREDICTABLE_RANDOM: This random generator (java.util.concurrent.ThreadLocalRandom) is predictable (details)
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
throws Exception { | ||
QueryRequest queryRequest = new QueryRequest(state.params); | ||
queryRequest.setBasePath( | ||
miniClusterState.nodes.get(ThreadLocalRandom.current().nextInt(state.nodeCount))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PREDICTABLE_RANDOM: This random generator (java.util.concurrent.ThreadLocalRandom) is predictable (details)
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
} | ||
} | ||
|
||
SolrMetricManager metricsManager = getCoreContainer().getMetricManager(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NULL_DEREFERENCE: object returned by getCoreContainer()
could be null and is dereferenced at line 729.
(at-me in a reply with help
or ignore
)
@@ -487,6 +488,14 @@ public long getIndexSize() { | |||
return size; | |||
} | |||
|
|||
public int getSegmentCount() { | |||
try { | |||
return withSearcher( solrIndexSearcher -> solrIndexSearcher.getRawReader().getIndexCommit().getSegmentCount()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THREAD_SAFETY_VIOLATION: Read/Write race. Non-private method SolrCore.getSegmentCount()
indirectly reads with synchronization from this.indexReaderFactory
. Potentially races with unsynchronized write in method SolrCore.initIndex(...)
.
Reporting because another access to the same memory occurs on a background thread, although this access may not.
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
@@ -212,7 +197,7 @@ public MiniSolrCloudCluster(int numServers, String hostContext, Path baseDir, St | |||
* @throws Exception if there was an error starting the cluster | |||
*/ | |||
public MiniSolrCloudCluster(int numServers, Path baseDir, String solrXml, JettyConfig jettyConfig) throws Exception { | |||
this(numServers, baseDir, solrXml, jettyConfig, null); | |||
this(numServers, baseDir, solrXml, jettyConfig, null, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THREAD_SAFETY_VIOLATION: Unprotected write. Non-private method MiniSolrCloudCluster(...)
indirectly mutates container util.ObjectReleaseTracker.OBJECTS
via call to Map.remove(...)
outside of synchronization.
Reporting because another access to the same memory occurs on a background thread, although this access may not.
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
ZkTestServer zkTestServer) throws Exception { | ||
this(numServers, baseDir, solrXml, jettyConfig, zkTestServer, Optional.empty()); | ||
ZkTestServer zkTestServer, boolean formatZkServer) throws Exception { | ||
this(numServers, baseDir, solrXml, jettyConfig, zkTestServer, Optional.empty(), formatZkServer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THREAD_SAFETY_VIOLATION: Unprotected write. Non-private method MiniSolrCloudCluster(...)
indirectly mutates container util.ObjectReleaseTracker.OBJECTS
via call to Map.remove(...)
outside of synchronization.
Reporting because another access to the same memory occurs on a background thread, although this access may not.
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
} | ||
if (securityJson.isPresent()) { // configure Solr security | ||
zkClient.makePath("/solr/security.json", securityJson.get().getBytes(Charset.defaultCharset()), true); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THREAD_SAFETY_VIOLATION: Unprotected write. Non-private method MiniSolrCloudCluster(...)
indirectly mutates container util.ObjectReleaseTracker.OBJECTS
via call to Map.remove(...)
outside of synchronization.
Reporting because another access to the same memory occurs on a background thread, although this access may not.
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
AtomicReference<DocCollection> state = new AtomicReference<>(); | ||
AtomicReference<Set<String>> liveNodesLastSeen = new AtomicReference<>(); | ||
try { | ||
getSolrClient().waitForState(collection, wait, unit, (n, c) -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
THREAD_SAFETY_VIOLATION: Unprotected write. Non-private method MiniSolrCloudCluster.waitForActiveCollection(...)
indirectly writes to field noggit.JSONParser.devNull.buf
outside of synchronization.
Reporting because another access to the same memory occurs on a background thread, although this access may not.
(at-me in a reply with help
or ignore
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@sonatype-lift ignore
eab2742
to
000e83a
Compare
Do we need to include a JFR or async-profiler recording profile? |
48570ed
to
9e6fa16
Compare
There is a sample config for JFR (that essentially turns on everything), but in general, these options are configured on the command line depending on what you are trying to look at. |
…icro benchmarks and performance comparisons & investigation.
9e6fa16
to
11ec45f
Compare
…icro benchmarks and performance comparisons & investigation. (apache#214)
Draft stripped down PR