Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public void execute( MavenSession session )
}

int degreeOfConcurrency = session.getRequest().getDegreeOfConcurrency();
if ( degreeOfConcurrency >= 2 )
if ( degreeOfConcurrency > 1 )
{
logger.info( "" );
logger.info( String.format( "Using the %s implementation with a thread count of %d",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public void build( MavenSession session, ReactorContext reactorContext, ProjectB
throws ExecutionException, InterruptedException
{
int nThreads = Math.min( session.getRequest().getDegreeOfConcurrency(), session.getProjects().size() );
boolean parallel = nThreads >= 2;
boolean parallel = nThreads > 1;
// Propagate the parallel flag to the root session and all of the cloned sessions in each project segment
session.setParallel( parallel );
for ( ProjectSegment segment : projectBuilds )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public CLIManager()
options.addOption( Option.builder( Character.toString( SHOW_VERSION ) ).longOpt( "show-version" ).desc( "Display version information WITHOUT stopping build" ).build() );
options.addOption( Option.builder( ENCRYPT_MASTER_PASSWORD ).longOpt( "encrypt-master-password" ).hasArg().optionalArg( true ).desc( "Encrypt master security password" ).build() );
options.addOption( Option.builder( ENCRYPT_PASSWORD ).longOpt( "encrypt-password" ).hasArg().optionalArg( true ).desc( "Encrypt server password" ).build() );
options.addOption( Option.builder( THREADS ).longOpt( "threads" ).hasArg().desc( "Thread count, for instance 2.0C where C is core multiplied" ).build() );
options.addOption( Option.builder( THREADS ).longOpt( "threads" ).hasArg().desc( "Thread count, for instance 4 (int) or 2C/2.5C (int/float) where C is core multiplied" ).build() );
options.addOption( Option.builder( LEGACY_LOCAL_REPOSITORY ).longOpt( "legacy-local-repository" ).desc( "Use Maven 2 Legacy Local Repository behaviour, ie no use of _remote.repositories. Can also be activated by using -Dmaven.legacyLocalRepo=true" ).build() );
options.addOption( Option.builder( BUILDER ).longOpt( "builder" ).hasArg().desc( "The id of the build strategy to use" ).build() );
options.addOption( Option.builder( NO_TRANSFER_PROGRESS ).longOpt( "no-transfer-progress" ).desc( "Do not display transfer progress when downloading or uploading" ).build() );
Expand Down
68 changes: 54 additions & 14 deletions maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.commons.cli.Option;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.UnrecognizedOptionException;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.maven.BuildAbort;
import org.apache.maven.InternalErrorException;
import org.apache.maven.Maven;
Expand Down Expand Up @@ -1584,18 +1585,11 @@ else if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && commandLine.hasOption

if ( threadConfiguration != null )
{
//
// Default to the standard multithreaded builder
//
request.setBuilderId( "multithreaded" );

if ( threadConfiguration.contains( "C" ) )
{
request.setDegreeOfConcurrency( calculateDegreeOfConcurrencyWithCoreMultiplier( threadConfiguration ) );
}
else
int degreeOfConcurrency = calculateDegreeOfConcurrency( threadConfiguration );
if ( degreeOfConcurrency > 1 )
{
request.setDegreeOfConcurrency( Integer.parseInt( threadConfiguration ) );
request.setBuilderId( "multithreaded" );
request.setDegreeOfConcurrency( degreeOfConcurrency );
}
}

Expand All @@ -1610,10 +1604,56 @@ else if ( commandLine.hasOption( CLIManager.ALSO_MAKE ) && commandLine.hasOption
return request;
}

int calculateDegreeOfConcurrencyWithCoreMultiplier( String threadConfiguration )
int calculateDegreeOfConcurrency( String threadConfiguration )
{
int procs = Runtime.getRuntime().availableProcessors();
return (int) ( Float.parseFloat( threadConfiguration.replace( "C", "" ) ) * procs );
if ( threadConfiguration.endsWith( "C" ) )
{
threadConfiguration = threadConfiguration.substring( 0, threadConfiguration.length() - 1 );

if ( !NumberUtils.isParsable( threadConfiguration ) )
{
throw new IllegalArgumentException( "Invalid threads core multiplier value: '" + threadConfiguration
+ "C'. Supported are int and float values ending with C." );
}

float coreMultiplier = Float.parseFloat( threadConfiguration );

if ( coreMultiplier <= 0.0f )
{
throw new IllegalArgumentException( "Invalid threads core multiplier value: '" + threadConfiguration
+ "C'. Value must be positive." );
}

int procs = Runtime.getRuntime().availableProcessors();
int threads = (int) ( coreMultiplier * procs );
return threads == 0 ? 1 : threads;
}
else
{
if ( !NumberUtils.isParsable( threadConfiguration ) )
{
throw new IllegalArgumentException( "Invalid threads value: '" + threadConfiguration
+ "'. Supported are int values." );
}

try
{
int threads = Integer.parseInt( threadConfiguration );

if ( threads <= 0 )
{
throw new IllegalArgumentException( "Invalid threads value: '" + threadConfiguration
+ "'. Value must be positive." );
}

return threads;
}
catch ( NumberFormatException e )
{
throw new IllegalArgumentException( "Invalid threads value: '" + threadConfiguration
+ "'. Supported are integer values." );
}
}
}

// ----------------------------------------------------------------------
Expand Down
58 changes: 39 additions & 19 deletions maven-embedder/src/test/java/org/apache/maven/cli/MavenCliTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
Expand All @@ -33,8 +34,6 @@
import java.io.File;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;

import org.apache.commons.cli.ParseException;
import org.apache.maven.Maven;
Expand All @@ -46,11 +45,12 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;
import org.mockito.InOrder;

public class MavenCliTest
{
private MavenCli cli;
MavenCli cli;

private String origBasedir;

Expand All @@ -76,23 +76,27 @@ public void tearDown()
}

@Test
public void testCalculateDegreeOfConcurrencyWithCoreMultiplier()
public void testCalculateDegreeOfConcurrency()
{
int cores = Runtime.getRuntime().availableProcessors();
// -T2.2C
assertEquals( (int) ( cores * 2.2 ), cli.calculateDegreeOfConcurrencyWithCoreMultiplier( "C2.2" ) );
// -TC2.2
assertEquals( (int) ( cores * 2.2 ), cli.calculateDegreeOfConcurrencyWithCoreMultiplier( "2.2C" ) );

try
{
cli.calculateDegreeOfConcurrencyWithCoreMultiplier( "CXXX" );
fail( "Should have failed with a NumberFormatException" );
}
catch ( NumberFormatException e )
{
// carry on
}
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "0" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "-1" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "0x4" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "1.0" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "1." ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "AA" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "C" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "C2.2C" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "C2.2" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "2C2" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "CXXX" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "XXXC" ) );

int cpus = Runtime.getRuntime().availableProcessors();
assertEquals( (int) ( cpus * 2.2 ), cli.calculateDegreeOfConcurrency( "2.2C" ) );
assertEquals( 1, cli.calculateDegreeOfConcurrency( "0.0001C" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "2.C" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "-2.2C" ) );
assertThrows( IllegalArgumentException.class, new ConcurrencyCalculator( "0C" ) );
}

@Test
Expand Down Expand Up @@ -371,4 +375,20 @@ public void testVersionStringWithoutAnsi() throws Exception
assertEquals( MessageUtils.stripAnsiCodes( versionOut ), versionOut );
}

class ConcurrencyCalculator implements ThrowingRunnable
Comment thread
michael-o marked this conversation as resolved.
{

private final String value;

public ConcurrencyCalculator( String value )
{
this.value = value;
}

@Override
public void run() throws Throwable
{
cli.calculateDegreeOfConcurrency( value );
}
}
}