Skip to content

The default of tests.jvms should not be capped #35259

Merged
alpar-t merged 6 commits intoelastic:masterfrom
alpar-t:run-more-tests-in-parallel
Nov 19, 2018
Merged

The default of tests.jvms should not be capped #35259
alpar-t merged 6 commits intoelastic:masterfrom
alpar-t:run-more-tests-in-parallel

Conversation

@alpar-t
Copy link
Copy Markdown
Contributor

@alpar-t alpar-t commented Nov 5, 2018

Lift the upper limit of the default.
We heuristically divide by two because it was found that increasing past
the number of physical cores does not yield benefits.

Lift the upper limit of the default.
We heuristically divide by two because it was found that increasing past
the number of physical cores does not yield benefits.
@alpar-t alpar-t requested a review from nik9000 November 5, 2018 15:39
@elasticmachine
Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-core-infra

Copy link
Copy Markdown
Member

@jasontedor jasontedor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left a comment to trigger some discussion.

project.tasks.withType(RandomizedTestingTask) {
jvm "${project.runtimeJavaHome}/bin/java"
parallelism System.getProperty('tests.jvms', 'auto')
parallelism System.getProperty('tests.jvms', String.valueOf(Runtime.getRuntime().availableProcessors() / 2))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have some concerns with this. Not all machines have hyper-threading, and not all machines have hyper-threading enabled. Some folks are choosing to disable hyper-threading because of security concerns. Intel is even releasing high-end processors that do not have hyper-threading (e.g., the i7-9700K, a workstation-class processor). On some machines, this will be too conservative.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ES itself uses Runtime.getRuntime().availableProcessors() as the default for the number of processors. Is there any reason we shouldn't match it? Maybe because that'd be a bit aggressive for tests. Some of them are multi-threaded and they all benefit from multi-threaded GC.

Maybe we make a hasHyperthreading variable? It'd be OS dependant, but easy enough to check on linux and mac. I dunno about windows.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dropping my 2 cents in, I feel like we should go with Runtime.getRuntime().availableProcessors(). I think the optimal value varies based on hardware, but I found on an i7-6850k (6 core, 12 threads) that -Dtests.jvms=12 was faster than -Dtests.jvms=6; I'll caveat saying that the last time I tested this was 6 months ago and I didn't test values in between so there could be an optimal value between number of physical cores and number of threads that a processor can handle. Given my feeling that this is going to be hardware dependent, I think we could take the simplest approach first and if needed consider adding detection for hyper threading later on?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI has 8 cores 16 threads right now, and running with 8 is faster than with 16 for sure.
It might not be related to hardware alone, but also to the number of the tests, as if there are few tests per worker the cost of starting up those workers is not worth it.

One can easily add systemProp.tests.jvms=6 to ~/.gradle/gradle.properties to customize this for their own hardware if the default is not appropriate.

@jasontedor I'm not entirely convinced it will be too conservative. On the processor you mentioned it will make no difference as it has 8 cores, and we'll continue using 4 on that processor, so there will be no change, as we currently cap at 4.
We will use fewer test workers on CPUs with fewer than 8 cores that have no or disabled hyper-threading.

I don't have a strong preference on the value we set this to. We could set it to the number of processors, but would prefer not to do hyper-threading detection ( or anything OS specific for that matter ) until we are absolutely sure we need it.

Maybe adding some documentation in TESTING will be enough.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jaymode In my experience, going above the number of physical cores has led to worse performance. I've seen this on an i7-5930K and an i7-6950X. 🤷‍♀️

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@atorok By conservative, I mean that it sets the default value at one that is lower than what I think the optimal value is.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jasontedor do you think that we should implement hyper-threading detection now ? I was trying to make the point that while the configuration will not be optimal for users with hyper threading disabled or absent, it will still be the same or close as we have Today as we cap to 4 threads right now. If you agree that this is the case we could start with this change to get some benefits in CI right away and then look at what else we can do to have a more generally useful default if this is common enough that we feel having systemProp.tests.jvms documented will not be sufficient.

@alpar-t
Copy link
Copy Markdown
Contributor Author

alpar-t commented Nov 14, 2018

@jasontedor @nik9000 @rjernst ready for review with hyper threading detection on Linux

static void applyCommonTestConfig(Project project) {
String defaultParallel = 'auto'
if (project.file("/proc/cpuinfo").exists()) {
Map<String, Integer> socketToCore = [:]
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment that we expect this branch for all linux distros. I'm not sure if they all have proper /proc filesystems but I think this is fairly reasonable. At worst they get auto instead.

project.tasks.withType(RandomizedTestingTask) {
jvm "${project.runtimeJavaHome}/bin/java"
parallelism System.getProperty('tests.jvms', 'auto')
parallelism System.getProperty('tests.jvms', defaultParallel)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra space.

TESTING.asciidoc Outdated
By default the tests run on up to 4 JVMs based on the number of cores. If you
want to explicitly specify the number of JVMs you can do so on the command
By default the tests run on multiple processes using half the available processors
as reported by the JVM.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you update this to mention physical cores?

if (name == "cpu cores") {
assert currentID.isEmpty() == false
socketToCore[currentID] = Integer.valueOf(value)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clear currentID here too I think.

}
}
})
defaultParallel = socketToCore.values().sum().toString();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gets the number of logical cores, I think. I thought we wanted the number of physical cores here. So socketToCore.size(). I think.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Socket is for when you might have multiple CPU socket, as in multiple CPU chips, thus the sum.

@alpar-t
Copy link
Copy Markdown
Contributor Author

alpar-t commented Nov 14, 2018

Thanks @nik9000 . Ready for another round.

@alpar-t
Copy link
Copy Markdown
Contributor Author

alpar-t commented Nov 15, 2018

@elasticmachine test thsi please

@alpar-t
Copy link
Copy Markdown
Contributor Author

alpar-t commented Nov 15, 2018

@elasticmachine test this please

Copy link
Copy Markdown
Member

@nik9000 nik9000 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I'll get the macOS one once you merge this.

@alpar-t alpar-t merged commit fda59ff into elastic:master Nov 19, 2018
@alpar-t alpar-t deleted the run-more-tests-in-parallel branch November 19, 2018 12:01
alpar-t added a commit that referenced this pull request Nov 19, 2018
Default to the number of physical cores across all sockets instead.
nik9000 added a commit to nik9000/elasticsearch that referenced this pull request Nov 21, 2018
In elastic#35259 we switched the default number of VMs to fork for unit tests to
the number of physical CPU cores. But because we could only get an accurate
count on machines with a normal `/proc` filesystem, macOS machine did not
pick up the new default. Given that macOS is a huge portion of developer
machines, we'd like to get the right default there. This does that.

It also moves the default-finding process from happening once per testing
task to happening once at startup. This seems like a good choice in general,
but a very good choice for macOS because we have to run a command to list
the count.
nik9000 added a commit that referenced this pull request Nov 27, 2018
In #35259 we switched the default number of VMs to fork for unit tests to
the number of physical CPU cores. But because we could only get an accurate
count on machines with a normal `/proc` filesystem, macOS machine did not
pick up the new default. Given that macOS is a huge portion of developer
machines, we'd like to get the right default there. This does that.

It also moves the default-finding process from happening once per testing
task to happening once at startup. This seems like a good choice in general,
but a very good choice for macOS because we have to run a command to list
the count.
nik9000 added a commit that referenced this pull request Nov 27, 2018
In #35259 we switched the default number of VMs to fork for unit tests to
the number of physical CPU cores. But because we could only get an accurate
count on machines with a normal `/proc` filesystem, macOS machine did not
pick up the new default. Given that macOS is a huge portion of developer
machines, we'd like to get the right default there. This does that.

It also moves the default-finding process from happening once per testing
task to happening once at startup. This seems like a good choice in general,
but a very good choice for macOS because we have to run a command to list
the count.
@jimczi jimczi added v7.0.0-beta1 and removed v7.0.0 labels Feb 7, 2019
@mark-vieira mark-vieira added the Team:Delivery Meta label for Delivery team label Nov 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Delivery/Build Build or test infrastructure >non-issue Team:Delivery Meta label for Delivery team v6.6.0 v7.0.0-beta1

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants