001package org.apache.maven.lifecycle.internal;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.codehaus.plexus.component.annotations.Component;
023import org.codehaus.plexus.component.annotations.Requirement;
024import org.codehaus.plexus.logging.Logger;
025
026import java.util.concurrent.ExecutorService;
027import java.util.concurrent.Executors;
028
029/**
030 * @since 3.0
031 */
032@Component( role = ThreadConfigurationService.class )
033public class ThreadConfigurationService
034{
035    @Requirement
036    private Logger logger;
037
038    private final int cpuCores;
039
040
041    public ThreadConfigurationService()
042    {
043        cpuCores = Runtime.getRuntime().availableProcessors();
044    }
045
046    public ThreadConfigurationService( Logger logger, int cpuCores )
047    {
048        this.logger = logger;
049        this.cpuCores = cpuCores;
050    }
051
052
053    public ExecutorService getExecutorService( String threadCountConfiguration, boolean perCoreThreadCount,
054                                               int largestBuildListSize )
055    {
056        Integer threadCount = getThreadCount( threadCountConfiguration, perCoreThreadCount, largestBuildListSize );
057        return getExecutorService( threadCount );
058
059
060    }
061
062    private ExecutorService getExecutorService( Integer threadCount )
063    {
064        if ( threadCount == null )
065        {
066            logger.info( "Building with unlimited threads" );
067            return Executors.newCachedThreadPool();
068        }
069
070        logger.info( "Building with " + threadCount + " threads" );
071        return Executors.newFixedThreadPool( threadCount );
072    }
073
074    /**
075     * Returns the thread count to use or null for unlimited threads.
076     *
077     * @param threadCountConfiguration The property passed from the command line.
078     * @param perCoreThreadCount       Indicates if the threa count should be scaled per cpu core.
079     * @param largestBuildListSize     the size of the largest module list (the number of modules)
080     * @return The number of threads to use or null if unlimited
081     */
082
083    Integer getThreadCount( String threadCountConfiguration, boolean perCoreThreadCount, int largestBuildListSize )
084    {
085        // Default to a value that is not larger than what we can use ;)
086        float threadCount = Math.min( cpuCores, largestBuildListSize );
087        if ( threadCountConfiguration != null )
088        {
089            try
090            {
091                threadCount = Float.parseFloat( threadCountConfiguration );
092            }
093            catch ( NumberFormatException e )
094            {
095                logger.warn(
096                    "Couldn't parse thread count, will default to " + threadCount + ": " + threadCountConfiguration );
097            }
098        }
099        if ( perCoreThreadCount )
100        {
101            threadCount = threadCount * cpuCores;
102        }
103
104        final int endResult = Math.round( threadCount );
105        if ( logger.isDebugEnabled() )
106        {
107            logger.debug( "Thread pool size: " + endResult );
108        }
109        return endResult;
110    }
111}