mirror of https://github.com/webpack/webpack.git
				
				
				
			
		
			
				
	
	
		
			178 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			178 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
"use strict";
 | 
						|
 | 
						|
const should = require("should");
 | 
						|
const path = require("path");
 | 
						|
const fs = require("fs");
 | 
						|
const async = require("async");
 | 
						|
var Test = require("mocha/lib/test");
 | 
						|
 | 
						|
const webpack = require("../lib/webpack");
 | 
						|
const Benchmark = require("benchmark");
 | 
						|
 | 
						|
describe("BenchmarkTestCases", function() {
 | 
						|
	const casesPath = path.join(__dirname, "benchmarkCases");
 | 
						|
	const tests = fs.readdirSync(casesPath).filter(function(folder) {
 | 
						|
		return folder.indexOf("_") < 0 && fs.existsSync(path.resolve(casesPath, folder, "webpack.config.js"));
 | 
						|
	});
 | 
						|
 | 
						|
	const baselinesPath = path.join(__dirname, "js", "benchmark-baselines");
 | 
						|
	const baselines = [];
 | 
						|
 | 
						|
	try {
 | 
						|
		fs.mkdirSync(path.join(__dirname, "js"));
 | 
						|
	} catch(e) {}
 | 
						|
	try {
 | 
						|
		fs.mkdirSync(baselinesPath);
 | 
						|
	} catch(e) {}
 | 
						|
 | 
						|
	before(function(done) {
 | 
						|
		this.timeout(270000);
 | 
						|
		const git = require("simple-git");
 | 
						|
		const rootPath = path.join(__dirname, "..");
 | 
						|
		getBaselineRevs(rootPath, (err, baselineRevisions) => {
 | 
						|
			if(err) return done(err);
 | 
						|
			async.eachSeries(baselineRevisions, (baselineInfo, callback) => {
 | 
						|
				const baselineRevision = baselineInfo.rev;
 | 
						|
				const baselinePath = path.resolve(baselinesPath, baselineRevision);
 | 
						|
				if(fs.existsSync(path.resolve(baselinePath, ".git"))) {
 | 
						|
					doLoadWebpack()
 | 
						|
				} else {
 | 
						|
					try {
 | 
						|
						fs.mkdirSync(baselinePath);
 | 
						|
					} catch(e) {}
 | 
						|
					git(baselinePath).raw(["--git-dir", path.join(rootPath, ".git"), "reset", "--hard", baselineRevision], err => {
 | 
						|
						if(err) return callback(err);
 | 
						|
						doLoadWebpack();
 | 
						|
					});
 | 
						|
				}
 | 
						|
 | 
						|
				function doLoadWebpack() {
 | 
						|
					const baselineWebpack = require(path.resolve(baselinePath, "lib/webpack.js"));
 | 
						|
					baselines.push({
 | 
						|
						name: baselineInfo.name,
 | 
						|
						rev: baselineRevision,
 | 
						|
						webpack: baselineWebpack
 | 
						|
					});
 | 
						|
					callback();
 | 
						|
				}
 | 
						|
			}, done)
 | 
						|
		});
 | 
						|
	});
 | 
						|
 | 
						|
	function getBaselineRevs(rootPath, callback) {
 | 
						|
		const git = require("simple-git")(rootPath);
 | 
						|
		const lastVersionTag = "v" + require("../package.json").version;
 | 
						|
		git.raw(["rev-list", "-n", "1", lastVersionTag], (err, resultVersion) => {
 | 
						|
			if(err) return callback(err);
 | 
						|
			const matchVersion = /^([a-f0-9]+)\s*$/.exec(resultVersion);
 | 
						|
			if(!matchVersion) return callback(new Error("Invalid result from git revparse"));
 | 
						|
			const revLastVersion = matchVersion[1];
 | 
						|
			git.raw(["rev-list", "--parents", "-n", "1", "HEAD"], (err, resultParents) => {
 | 
						|
				if(err) return callback(err);
 | 
						|
				const match = /^([a-f0-9]+)\s*([a-f0-9]+)\s*([a-f0-9]+)?\s*$/.exec(resultParents);
 | 
						|
				if(!match) return callback(new Error("Invalid result from git rev-list"));
 | 
						|
				const head = match[1]
 | 
						|
				const parent1 = match[2];
 | 
						|
				const parent2 = match[3];
 | 
						|
				if(parent2 && parent1) {
 | 
						|
					return callback(null, [{
 | 
						|
						name: "HEAD",
 | 
						|
						rev: head
 | 
						|
					}, head !== revLastVersion && {
 | 
						|
						name: lastVersionTag,
 | 
						|
						rev: revLastVersion
 | 
						|
					}, parent1 !== revLastVersion && head !== revLastVersion && {
 | 
						|
						name: "base",
 | 
						|
						rev: parent1
 | 
						|
					}].filter(Boolean));
 | 
						|
				} else if(parent1) {
 | 
						|
					return callback(null, [{
 | 
						|
						name: "HEAD",
 | 
						|
						rev: head
 | 
						|
					}, head !== revLastVersion && {
 | 
						|
						name: lastVersionTag,
 | 
						|
						rev: revLastVersion
 | 
						|
					}].filter(Boolean));
 | 
						|
				} else {
 | 
						|
					return callback(new Error("No baseline found"));
 | 
						|
				}
 | 
						|
			});
 | 
						|
		});
 | 
						|
	}
 | 
						|
 | 
						|
	function runBenchmark(webpack, config, callback) {
 | 
						|
		// warmup
 | 
						|
		const warmupCompiler = webpack(config, (err, stats) => {
 | 
						|
			warmupCompiler.purgeInputFileSystem();
 | 
						|
			const bench = new Benchmark(function(deferred) {
 | 
						|
				const compiler = webpack(config, (err, stats) => {
 | 
						|
					compiler.purgeInputFileSystem();
 | 
						|
					if(err) {
 | 
						|
						deferred.reject(err);
 | 
						|
						return;
 | 
						|
					}
 | 
						|
					if(stats.hasErrors()) {
 | 
						|
						deferred.reject(new Error(stats.toJson().errors.join("\n\n")));
 | 
						|
						return;
 | 
						|
					}
 | 
						|
					deferred.resolve();
 | 
						|
				});
 | 
						|
			}, {
 | 
						|
				maxTime: 30,
 | 
						|
				defer: true,
 | 
						|
				initCount: 1,
 | 
						|
				onComplete: function() {
 | 
						|
					callback(null, bench.stats);
 | 
						|
				},
 | 
						|
				onError: callback
 | 
						|
			});
 | 
						|
			bench.run({
 | 
						|
				async: true
 | 
						|
			});
 | 
						|
		});
 | 
						|
	}
 | 
						|
 | 
						|
	tests.forEach(testName => {
 | 
						|
		const testDirectory = path.join(casesPath, testName);
 | 
						|
		let headStats = null;
 | 
						|
		const suite = describe(testName, function() {});
 | 
						|
		it(`${testName} create benchmarks`, function() {
 | 
						|
			baselines.forEach(baseline => {
 | 
						|
				let baselineStats = null;
 | 
						|
 | 
						|
				function it(title, fn) {
 | 
						|
					const test = new Test(title, fn);
 | 
						|
					suite.addTest(test);
 | 
						|
				}
 | 
						|
				it(`should benchmark ${baseline.name} (${baseline.rev})`, function(done) {
 | 
						|
					this.timeout(180000);
 | 
						|
					const outputDirectory = path.join(__dirname, "js", "benchmark", `baseline-${baseline.name}`, testName);
 | 
						|
					const config = Object.create(require(path.join(testDirectory, "webpack.config.js")));
 | 
						|
					config.output = Object.create(config.output || {});
 | 
						|
					if(!config.context) config.context = testDirectory;
 | 
						|
					if(!config.output.path) config.output.path = outputDirectory;
 | 
						|
					runBenchmark(baseline.webpack, config, (err, stats) => {
 | 
						|
						if(err) return done(err);
 | 
						|
						console.log(`        ${baseline.name} ${Math.round(stats.mean * 1000)}ms ± ${Math.round(stats.deviation * 1000)}ms`);
 | 
						|
						if(baseline.name === "HEAD")
 | 
						|
							headStats = stats;
 | 
						|
						else
 | 
						|
							baselineStats = stats;
 | 
						|
						done();
 | 
						|
					});
 | 
						|
				});
 | 
						|
 | 
						|
				if(baseline.name !== "HEAD") {
 | 
						|
					it(`HEAD should not be slower than ${baseline.name} (${baseline.rev})`, function() {
 | 
						|
						if(baselineStats.mean + baselineStats.deviation < headStats.mean - headStats.deviation) {
 | 
						|
							throw new Error(`HEAD (${baselineStats.mean} ± ${baselineStats.deviation}) is slower than ${baseline.name} (${headStats.mean} ± ${headStats.deviation})`);
 | 
						|
						} else if(baselineStats.mean - baselineStats.deviation > headStats.mean + headStats.deviation) {
 | 
						|
							console.log(`======> HEAD is ${Math.round(baselineStats.mean / headStats.mean * 100 - 100)}% faster than ${baseline.name}!`);
 | 
						|
						}
 | 
						|
					});
 | 
						|
				}
 | 
						|
			});
 | 
						|
		});
 | 
						|
	});
 | 
						|
});
 |