/*
* Copyright (C) 2011 Laurent Caillette
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.novelang.nhovestone;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.imageio.ImageIO;
import com.google.common.collect.ImmutableList;
import org.apache.commons.io.output.FileWriterWithEncoding;
import org.apache.commons.lang.SystemUtils;
import static org.novelang.KnownVersions.*;
import org.novelang.Version;
import org.novelang.VersionFormatException;
import org.novelang.common.FileTools;
import org.novelang.logger.Logger;
import org.novelang.logger.LoggerFactory;
import org.novelang.nhovestone.report.Grapher;
import org.novelang.nhovestone.scenario.ScenarioLibrary;
import org.novelang.nhovestone.scenario.TimeMeasurement;
import org.novelang.nhovestone.scenario.TimeMeasurer;
import org.novelang.outfit.DefaultCharset;
import org.novelang.outfit.EnvironmentTools;
import org.novelang.outfit.Husk;
import org.novelang.outfit.LogbackConfigurationTools;
import org.novelang.outfit.shell.ProcessCreationException;
import org.novelang.outfit.shell.ProcessInitializationException;
/**
* Main class generating the Nhovestone report.
*
* @author Laurent Caillette
*/
public class Nhovestone {
private Nhovestone() { }
public static void main( final String... arguments )
throws
IOException,
ProcessCreationException,
VersionFormatException,
InterruptedException,
ProcessInitializationException
{
LogbackConfigurationTools.fixLogDirectory( new File( SystemUtils.USER_DIR ) ) ;
LoggerFactory.configurationComplete() ;
final Logger log = LoggerFactory.getLogger( Nhovestone.class );
log.info( "Running with command-line arguments ", ImmutableList.of( arguments ), "..." ) ;
EnvironmentTools.logSystemProperties() ;
final File scenariiDirectory ;
final File versionsDirectory ;
final Iterable< Version > versions ;
if( arguments.length == 3 ) {
scenariiDirectory = FileTools.createFreshDirectory( arguments[ 0 ] ) ;
versionsDirectory = new File( arguments[ 1 ] ) ;
versions = NhovestoneTools.parseVersions( arguments[ 2 ] ) ;
} else {
if( arguments.length != 0 ) {
throw new IllegalArgumentException( "Usage: " + Nhovestone.class.getSimpleName() +
" [ < scenarii-dir > < distrib-dir > < comma-separated-versions > ]" ) ;
}
scenariiDirectory = FileTools.createFreshDirectory( "_nhovestone" ) ;
versionsDirectory = new File( "distrib" ) ;
versions = Arrays.asList( VERSION_0_41_0, VERSION_0_38_1, VERSION_0_35_0 ) ;
}
run( log, scenariiDirectory, versionsDirectory, versions, 1000, 10000, 32 ) ;
System.exit( 0 ) ;
}
public static void run(
final Logger log,
final File scenariiDirectory,
final File versionsDirectory,
final Iterable<Version> versions,
final int warmupIterationCount,
final int maximumIterations,
final int jvmHeapSizeMegabytes
)
throws
IOException,
ProcessCreationException,
InterruptedException,
ProcessInitializationException
{
final ScenarioLibrary.ConfigurationForTimeMeasurement baseConfiguration =
Husk.create( ScenarioLibrary.ConfigurationForTimeMeasurement.class )
.withWarmupIterationCount( warmupIterationCount )
.withMaximumIterations( maximumIterations )
.withScenariiDirectory( scenariiDirectory )
.withInstallationsDirectory( versionsDirectory )
.withVersions( versions )
.withFirstTcpPort( 9900 )
.withJvmHeapSizeMegabytes( jvmHeapSizeMegabytes )
.withMeasurer( new TimeMeasurer() )
;
runScenario( baseConfiguration
.withScenarioName( "Single ever-growing Novella" )
.withUpsizerFactory( ScenarioLibrary.createNovellaLengthUpsizerFactory( new Random( 0L ) ) )
,
false,
log
) ;
runScenario( baseConfiguration
.withScenarioName( "Increasing Novella count" )
.withUpsizerFactory( ScenarioLibrary.createNovellaCountUpsizerFactory( new Random( 0L ) ) )
,
true,
log
) ;
writeNhovestoneParameters(
new File( scenariiDirectory, "report-parameters.novella" ),
baseConfiguration
) ;
}
private static void writeNhovestoneParameters(
final File parametersFile,
final Scenario.Configuration< ?, ?, ? > configuration
) throws IOException {
final Writer writer = new FileWriterWithEncoding( parametersFile, DefaultCharset.SOURCE ) ;
final PrintWriter printWriter = new PrintWriter( writer ) ;
try {
printWriter.println( "== VERSIONS" ) ;
printWriter.println( "" ) ;
for( final Version version : configuration.getVersions() ) {
printWriter.println( "- `" + version.getName() + "`" ) ;
}
printWriter.println( "" ) ;
printWriter.println( "== NHOVESTONEPARAMETERS" ) ;
printWriter.println( "" ) ;
printRow( printWriter, "Warmup iterations", configuration.getWarmupIterationCount() ) ;
printRow( printWriter, "Maximum iterations", configuration.getMaximumIterations() ) ;
printRow( printWriter, "JVM heap size (MB)", configuration.getJvmHeapSizeMegabytes() ) ;
printWriter.println( "" ) ;
printWriter.println( "== JVMCHARACTERISTICS" ) ;
printWriter.println( "" ) ;
printRow( printWriter, "java.version" ) ;
printRow( printWriter, "java.vm.name" ) ;
printRow( printWriter, "os.arch" ) ;
printRow( printWriter, "os.name" ) ;
printRow( printWriter, "os.version" ) ;
printRow( printWriter, "Available processors", Runtime.getRuntime().availableProcessors() ) ;
} finally {
printWriter.close() ;
}
}
private static void printRow( final PrintWriter printWriter, final String systemPropertyName ) {
final String systemPropertyValue = System.getProperty( systemPropertyName ) ;
if( systemPropertyValue != null ) {
printRow( printWriter, systemPropertyName, systemPropertyValue ) ;
}
}
private static void printRow(
final PrintWriter printWriter,
final String cell1,
final int cell2
) {
printRow( printWriter, cell1, "" + cell2 ) ;
}
private static void printRow(
final PrintWriter printWriter,
final String cell1,
final String cell2
) {
printWriter.println( "| `" + cell1 + "` | `" + cell2 + "` | " ) ;
}
private static void runScenario(
final ScenarioLibrary.ConfigurationForTimeMeasurement configuration,
final boolean showUpsizingCount,
final Logger logger
)
throws
IOException,
ProcessCreationException,
InterruptedException,
ProcessInitializationException
{
final Scenario< Long, TimeMeasurement > scenario =
new Scenario< Long, TimeMeasurement >( configuration ) ;
scenario.run() ;
final Map< Version, MeasurementBundle< TimeMeasurement > > measurements =
scenario.getMeasurements() ;
final List< Long > upsizings = scenario.getUpsizings() ;
final BufferedImage image = Grapher.create( upsizings, measurements, showUpsizingCount ) ;
final File imageDestinationFile = new File(
configuration.getScenariiDirectory(),
FileTools.sanitizeFileName( configuration.getScenarioName() ) + ".png"
) ;
ImageIO.write( image, "png", imageDestinationFile ) ;
logger.info( "Wrote ", imageDestinationFile.getAbsolutePath() ) ;
}
}