-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Configure thread pools size relative to the number of available cores #16303
Conversation
8eeb7aa
to
fd7c5ed
Compare
fd7c5ed
to
9a92ef8
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.
Added some comments. Overall I like this generic approach over specific change in #16287, but would also let other maintainers chime in w.r.t whether this should go in airlift (and the syntax)
private int deletionThreads = max(1, getRuntime().availableProcessors() / 2); | ||
private int recoveryThreads = 10; | ||
private int organizationThreads = 5; | ||
private ThreadsCount deletionThreads = ThreadsCount.valueOf("0.5C"); |
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.
is this a separate bugfix as looks like previous impl would always cap it to 1? if so, i'd keep it in a separate commit/PR. I'm not sure about whether the previous value was intentional. cc @electrum
@@ -51,13 +49,13 @@ public void testDefaults() | |||
.setOrcTinyStripeThreshold(DataSize.of(8, MEGABYTE)) | |||
.setOrcLazyReadSmallRanges(true) | |||
.setOrcNestedLazy(true) | |||
.setDeletionThreads(max(1, getRuntime().availableProcessors() / 2)) | |||
.setDeletionThreads("0.5C") |
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.
same comment about max here
@@ -54,7 +50,7 @@ | |||
private DataSize maxLocalExchangeBufferSize = DataSize.of(32, Unit.MEGABYTE); | |||
private DataSize maxIndexMemoryUsage = DataSize.of(64, Unit.MEGABYTE); | |||
private boolean shareIndexLoading; | |||
private int maxWorkerThreads = Runtime.getRuntime().availableProcessors() * 2; | |||
private ThreadsCount maxWorkerThreads = ThreadsCount.valueOf("2C"); |
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.
for many of these, documentation wuold need to be updated right?
|
||
import static java.lang.Math.round; | ||
|
||
public record ThreadsCount(int threadsCount) |
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.
is this something that should belong in airlift like Duration/Datasize? @trinodb/maintainers
} | ||
|
||
@LegacyConfig("task.shard.max-threads") | ||
@Config("task.max-worker-threads") | ||
public TaskManagerConfig setMaxWorkerThreads(int maxWorkerThreads) | ||
public TaskManagerConfig setMaxWorkerThreads(String maxWorkerThreads) |
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 think we should be able to use ThreadsCount parameter instead of string: https://github.com/airlift/airlift/blob/master/configuration/src/main/java/io/airlift/configuration/ConfigurationFactory.java#L666
is there a reason to do otherwise?
private void assertInvalidValue(String value, String expectedMessage) | ||
{ | ||
try { | ||
ThreadsCount.valueOf(value); |
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.
nit: use assertThatThrownBy
@phd3 I agree that this could be a part of the airlift and applied there as well |
I am concerned about additional complexity this introduced. Is it outweighed with value added? (this doesn't mean we shouldn't auto-tune. We should auto-tune out-of-the-box, but i understand this is now what this PR is doing) |
I like this in general. There are probably various configs we could update to have better defaults. I don’t like the “C2” syntax since it’s easy to mix up with “2C”. I also question if this is needed. What’s the use case? Do we ever require power of two? If we do, we could make rounding automatic for those? |
@electrum there are cases when power of two size is required and actually validated. What would be a better syntax? |
} | ||
|
||
private static final String PER_CORE_SUFFIX = "C"; | ||
private static final String PER_CORE_NEXT_POWER_OF_2_SUFFIX = "C2"; |
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.
It's confusing as it suggest it's 2
number of cores rather than pow of two. See how we deal with it in io.trino.execution.TaskManagerConfig#taskConcurrency
.
I think user should just provide number that is power of two. These config properties shouldn't be touched by user too much anyway if they don't know what they are doing.
core/trino-main/src/main/java/io/trino/execution/TaskManagerConfig.java
Outdated
Show resolved
Hide resolved
@wendigo so I read this is as we generally agree that this can move into airlift. Based on some comments above - looks like we still need to discuss on the syntax simplification especially around C2. I like the suggestion in #16303 (comment). @findepi do you feel strongly about the overhead if somehow the C2 scenario is simplified? |
Extracted to airlift/units#31 |
9a92ef8
to
de3fc07
Compare
@phd3 @Praveen2112 @sopel39 this type is now coming from airlift/units |
New type was introduced in the airlift/units 1.10
de3fc07
to
33d39b3
Compare
// newer units version in JDBC due to different JDK target. | ||
// It is temporary solution until client and JDBC are moved to JDK 11+. | ||
// This class is added to test classes, so it won't be a part of the jdbc driver. | ||
public class ThreadCount |
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.
Why would we need this copy?
plase remove
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.
Jdk 8 target and newer units is on 11
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 know. but trino-jdbc should avoid having classes in io.airlift
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.
It’s the matter of test scope
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.
So this class resides in trino-jdbc tests, it is unused there, and must remain API-compatible with the newly added ThreadCount class in units. Does this sounds like we're doing something wrong here?
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.
Yeah. Keeping JDBC on JDK 8 which prohibits upgrading dependencies like airlift units
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.
If i understand correctly, trino-jdbc ships units 1.7 for its own use and it downgrades units version for test scope resulting in NoClassDefFoundError when we try to start trino server.
unless maven allows us to package units 1.7 but still use a newer version for test classpath, i see the following options:
- stop using airlift units in trino-jdbc (perhaps copying & repackaging necessary classed if this is indeed warranted)
- move jdbc tests that require trino server to a separate module, where we will use modern units.
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.
Moving tests seems like a better option
@wendigo i'd suggest to split this PR and configure eg |
I tried using ThreadCount internally and realized it's not really a value object. It's just a parser public class ThreadCountParser
{
private static final String PER_CORE_SUFFIX = "C";
private static final Supplier<Integer> AVAILABLE_PROCESSORS = memoize(MachineInfo::getAvailablePhysicalProcessorCount);
public static final ThreadCountParser DEFAULT = new ThreadCountParser(AVAILABLE_PROCESSORS);
private final Supplier<Integer> coreCount;
@VisibleForTesting
ThreadCountParser(Supplier<Integer> coreCount);
public int parse(String value);
} this would result in simpler code, simpler concepts added bonus? the parser would belong to Trino codebase (or airlift), not units |
@@ -53,7 +51,7 @@ public class TaskManagerConfig | |||
private DataSize maxLocalExchangeBufferSize = DataSize.of(128, Unit.MEGABYTE); | |||
private DataSize maxIndexMemoryUsage = DataSize.of(64, Unit.MEGABYTE); | |||
private boolean shareIndexLoading; | |||
private int maxWorkerThreads = Runtime.getRuntime().availableProcessors() * 2; | |||
private ThreadCount maxWorkerThreads = ThreadCount.valueOf("2C"); |
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.
This is two separate changes
- the main one per PR title: allowing to configure
n
inn * number of cores
formula - how the "number of cores" is determined
I think the changes should go as separate things. The (1) is obvious, but the (2) is tricky and needs to be thoroughly code commented
int availableProcessorCount = Runtime.getRuntime().availableProcessors(); | ||
int totalPhysicalProcessorCount = availableProcessorCount; | ||
if ("amd64".equals(osArch) || "x86_64".equals(osArch)) { | ||
OptionalInt procInfo = tryReadFromProcCpuinfo(); |
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.
How is it better than Runtime.getRuntime().availableProcessors()
and why take min
of the two instead of just using "the better one"?
This should be documented.
} | ||
} | ||
|
||
// cap available processor count to container cpu quota (if there is any). |
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.
Why container quota is inspected for certain architectures only?
Worker threads defaults to 2*#cores. This commit allows configuration to be #cores based too. Extracted from trinodb#16303 Co-authored-by: Mateusz "Serafin" Gajewski <[email protected]>
Worker threads defaults to 2*#cores. This commit allows configuration to be #cores based too. Extracted from #16303 Co-authored-by: Mateusz "Serafin" Gajewski <[email protected]>
Description
Alternative to #16287
It makes it possible to configure threads pools using more sophisticated syntax:
Additional context and related issues
Release notes
( ) This is not user-visible or docs only and no release notes are required.
( ) Release notes are required, please propose a release note for me.
( ) Release notes are required, with the following suggested text: