Skip to content

Commit ff024fb

Browse files
[GR-64207] [GR-65006] Refactor --parallelism and java.util.concurrent.ForkJoinPool.common.parallelism system property handling.
PullRequest: graal/20869
2 parents 4e6f52c + 212e843 commit ff024fb

File tree

2 files changed

+27
-37
lines changed

2 files changed

+27
-37
lines changed

substratevm/CHANGELOG.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ This changelog summarizes major changes to GraalVM Native Image.
2828
* (GR-47881) Remove the total number of loaded types, fields, and methods from the build output, deprecated these metrics in the build output schema, and removed already deprecated build output metrics.
2929
* (GR-64619) Missing registration errors are now subclasses of `LinkageError`.
3030
* (GR-63591) Resource bundle registration is now included as part of the `"resources"` section of _reachability-metadata.json_. When this is the case, the bundle name is specified using the `"bundle"` field.
31-
* (GR-57827) Move the initialization of security providers from build time to runtime.
3231
* (GR-57827) Security providers can now be initialized at run time (instead of build time) when using the option `--future-defaults=all` or `--future-defaults=run-time-initialized-jdk`.
3332
Run-time initialization of security providers helps reduce image heap size by avoiding unnecessary objects inclusion.
3433
* (GR-48191) Enable lambda classes to be registered for reflection and serialization in _reachability-metadata.json_. The format is detailed [here](https://github.com/oracle/graal/blob/master/docs/reference-manual/native-image/ReachabilityMetadata.md).

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageOptions.java

Lines changed: 27 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import java.nio.file.Paths;
3232
import java.text.SimpleDateFormat;
3333
import java.util.Date;
34-
import java.util.concurrent.CompletableFuture;
3534
import java.util.concurrent.ForkJoinPool;
3635

3736
import org.graalvm.collections.EconomicMap;
@@ -47,6 +46,7 @@
4746
import com.oracle.svm.core.util.UserError;
4847
import com.oracle.svm.hosted.classinitialization.ClassInitializationOptions;
4948
import com.oracle.svm.hosted.util.CPUType;
49+
import com.oracle.svm.util.LogUtils;
5050
import com.oracle.svm.util.StringUtil;
5151

5252
import jdk.graal.compiler.options.Option;
@@ -185,59 +185,50 @@ public static CStandards getCStandard() {
185185
}
186186
}
187187

188+
private static int availableProcessors() {
189+
return Runtime.getRuntime().availableProcessors();
190+
}
191+
188192
/**
189193
* Configures the number of threads of the common pool.
190194
*/
191195
private static final String PARALLELISM_OPTION_NAME = "parallelism";
192196
@APIOption(name = PARALLELISM_OPTION_NAME)//
193197
@Option(help = "The maximum number of threads the build process is allowed to use.")//
194-
public static final HostedOptionKey<Integer> NumberOfThreads = new HostedOptionKey<>(Math.max(1, Math.min(Runtime.getRuntime().availableProcessors(), 32)), key -> {
198+
public static final HostedOptionKey<Integer> NumberOfThreads = new HostedOptionKey<>(Math.min(availableProcessors(), 32), key -> {
195199
int numberOfThreads = key.getValue();
196200
if (numberOfThreads < 1) {
197201
throw UserError.abort("The number of threads was set to %s. Please set the '--%s' option to at least 1.", numberOfThreads, PARALLELISM_OPTION_NAME);
198202
}
203+
int numAvailableProcessors = availableProcessors();
204+
if (numberOfThreads > numAvailableProcessors) {
205+
LogUtils.warning("Specified parallelism exceeds the number of available processors (%d).", numAvailableProcessors);
206+
}
199207
});
200208

201209
public static int getActualNumberOfThreads() {
202-
int commonThreadParallelism = ForkJoinPool.getCommonPoolParallelism();
203-
if (NumberOfThreads.getValue() == 1) {
204-
/*
205-
* Overriding zero parallelism must ensure at least one worker, but due to other
206-
* backward compatibility constraints, it ensures two.
207-
*/
208-
assert commonThreadParallelism == 2 : "The common pool with zero parallelism has two worker threads.";
209-
/* The common pool with zero parallelism has no actual threads. */
210-
commonThreadParallelism = 0;
210+
String commonParallelismProperty = System.getProperty("java.util.concurrent.ForkJoinPool.common.parallelism");
211+
if (commonParallelismProperty != null) {
212+
return Integer.parseInt(commonParallelismProperty);
213+
} else {
214+
return NumberOfThreads.getValue();
211215
}
212-
/*
213-
* Main thread plus common pool threads. setCommonPoolParallelism() asserts that this number
214-
* matches NumberOfThreads.
215-
*/
216-
return 1 + commonThreadParallelism;
217216
}
218217

219-
/**
220-
* The --parallelism flag controls the number of threads used during native image builds.
221-
* <p>
222-
* There are two ways to apply this value to set the thread count in the common pool: using
223-
* system properties (though this approach is strongly discouraged in recent JDK versions), and
224-
* using the {@link ForkJoinPool#setParallelism} method.
225-
* <p>
226-
* By default, the common pool's parallelism level (without explicitly setting it via system
227-
* properties or method) equals the number of available processors minus one.
228-
* <p>
229-
* If zero parallelism is desired, the flag should be set to {@code 1} (main thread only). While
230-
* this value can be assigned to the common pool, note that when using
231-
* {@link CompletableFuture}, the minimal effective parallelism becomes two due to its internal
232-
* pool requirements (see CompletableFuture#ASYNC_POOL). Therefore, the actual thread count must
233-
* be incremented by one.
234-
*/
235218
public static void setCommonPoolParallelism(OptionValues optionValues) {
236-
int numberOfCommonPoolThreads = NativeImageOptions.NumberOfThreads.getValueOrDefault(optionValues.getMap());
237-
if (numberOfCommonPoolThreads == 1) {
238-
numberOfCommonPoolThreads += 1;
219+
int targetParallelism = Math.max(1, NumberOfThreads.getValueOrDefault(optionValues.getMap()) - 1);
220+
if (ForkJoinPool.commonPool().getParallelism() == targetParallelism) {
221+
/* Nothing to do. */
222+
return;
223+
}
224+
225+
try {
226+
ForkJoinPool.commonPool().setParallelism(targetParallelism);
227+
} catch (UnsupportedOperationException e) {
228+
if (NumberOfThreads.hasBeenSet(optionValues)) {
229+
LogUtils.warning("Could not apply the '--parallelism' option due to the `java.util.concurrent.ForkJoinPool.common.parallelism` system property being set as the same time.");
230+
}
239231
}
240-
ForkJoinPool.commonPool().setParallelism(numberOfCommonPoolThreads);
241232
}
242233

243234
@Option(help = "Deprecated, option no longer has any effect", deprecated = true, deprecationMessage = "Please use '--parallelism' instead.")//

0 commit comments

Comments
 (0)