added optimizer scripts and some code style improvements

This commit is contained in:
logsol 2015-03-09 04:56:28 +01:00
parent 6b472dc134
commit 5f5fec5b10
16 changed files with 397 additions and 36 deletions

View file

@ -1,4 +1,9 @@
define(function () { define([
],
function () {
"use strict";
function Key () { function Key () {
this._active = false; this._active = false;

View file

@ -20,12 +20,6 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, Nc, reque
"use strict"; "use strict";
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}
function GameController (options) { function GameController (options) {
this.clientIsReady = false; this.clientIsReady = false;
@ -277,6 +271,12 @@ function (Parent, Box2D, PhysicsEngine, ViewManager, PlayerController, Nc, reque
GameController.prototype.destroy = function() { GameController.prototype.destroy = function() {
if (!window.cancelAnimationFrame) {
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}
cancelAnimationFrame(this.animationRequestId); cancelAnimationFrame(this.animationRequestId);
Parent.prototype.destroy.call(this); Parent.prototype.destroy.call(this);

View file

@ -118,5 +118,4 @@ function (Parent, Settings, Nc) {
}; };
return Me; return Me;
});
})

View file

@ -62,4 +62,4 @@ function (Parent, Settings, DomController, Box2D, Nc, DebugDraw, DebugLayer) {
} }
return Engine; return Engine;
}) });

View file

@ -11,13 +11,12 @@ function (Settings, Nc, Screenfull, Graph, PointerLockManager) {
"use strict"; "use strict";
function DomController() { function DomController() {
this.canvas = document.getElementById("canvas"); this.canvas = null;
this.stats = null; this.stats = null;
this.ping = null; this.ping = null;
this.nickContainer = null; this.nickContainer = null;
this.fpsContainer = ""; this.fpsContainer = "";
this.devToolsContainer = null;
this.devToolsContainer = document.getElementById("menuBar");
this.initDevTools(); this.initDevTools();
} }
@ -27,6 +26,9 @@ function (Settings, Nc, Screenfull, Graph, PointerLockManager) {
var self = this; var self = this;
var li, button, label; var li, button, label;
this.canvas = document.getElementById("canvas");
this.devToolsContainer = document.getElementById("menuBar");
// create back to menu button // create back to menu button
li = document.createElement("li"); li = document.createElement("li");
li.id = "back-to-menu"; li.id = "back-to-menu";

View file

@ -9,13 +9,6 @@ define([
function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) { function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) {
"use strict"; "use strict";
var AVAILABLE_MESH_FILTERS = {
"blur": PIXI.BlurFilter,
"desaturate": PIXI.GrayFilter,
"pixelate": PIXI.PixelateFilter,
"colorRangeReplace": ColorRangeReplaceFilter,
};
function Layer (name, parallaxSpeed) { function Layer (name, parallaxSpeed) {
Parent.call(this, name, parallaxSpeed); Parent.call(this, name, parallaxSpeed);
@ -60,6 +53,15 @@ function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) {
Layer.prototype = Object.create(Parent.prototype); Layer.prototype = Object.create(Parent.prototype);
Layer.prototype.getAvailableMeshFilters = function() {
return {
"blur": PIXI.BlurFilter,
"desaturate": PIXI.GrayFilter,
"pixelate": PIXI.PixelateFilter,
"colorRangeReplace": ColorRangeReplaceFilter,
};
};
Layer.prototype.getContainer = function() { Layer.prototype.getContainer = function() {
return this.container; return this.container;
}; };
@ -135,11 +137,11 @@ function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) {
Layer.prototype.addFilter = function(mesh, filterName, options) { Layer.prototype.addFilter = function(mesh, filterName, options) {
if (!AVAILABLE_MESH_FILTERS.hasOwnProperty(filterName)) { if (!this.getAvailableMeshFilters().hasOwnProperty(filterName)) {
throw new Exception('Filter ' + filterName + ' is not available'); throw new Exception('Filter ' + filterName + ' is not available');
} }
var MeshFilter = AVAILABLE_MESH_FILTERS[filterName]; var MeshFilter = this.getAvailableMeshFilters()[filterName];
var filter = new MeshFilter(); var filter = new MeshFilter();
switch (filterName) { switch (filterName) {
@ -189,7 +191,7 @@ function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) {
return; return;
} }
var MeshFilter = AVAILABLE_MESH_FILTERS[options.filter]; var MeshFilter = this.getAvailableMeshFilters()[options.filter];
filters = filters.filter(function(filter){ filters = filters.filter(function(filter){
return !filter instanceof MeshFilter; return !filter instanceof MeshFilter;
@ -271,9 +273,6 @@ function (Parent, PIXI, ColorRangeReplaceFilter, Settings, ColorConverter) {
this.container.x += Settings.STAGE_WIDTH / 2; this.container.x += Settings.STAGE_WIDTH / 2;
this.container.y += Settings.STAGE_HEIGHT / 2; this.container.y += Settings.STAGE_HEIGHT / 2;
} }
}; };
return Layer; return Layer;

View file

@ -1,4 +1,7 @@
define(function() { define([
],
function () {
var ItemSettings = { var ItemSettings = {

View file

@ -1,4 +1,7 @@
define(function() { define([
],
function () {
var Settings = { var Settings = {
STAGE_WIDTH: 600, STAGE_WIDTH: 600,

View file

@ -1,4 +1,7 @@
define(function () { define([
],
function () {
function PlayerController (player) { function PlayerController (player) {

View file

@ -96,4 +96,4 @@ define([
} }
return Level; return Level;
}) });

View file

@ -213,4 +213,4 @@ define([
} }
return TiledLevel; return TiledLevel;
}) });

View file

@ -1,4 +1,7 @@
define(function () { define([
],
function () {
function User (id, options) { function User (id, options) {
this.id = id; this.id = id;

View file

@ -1,4 +1,7 @@
define(function() { define([
],
function () {
/* /*
* Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com

View file

@ -7,8 +7,6 @@ function (Nc, childProcess) {
"use strict"; "use strict";
var fork = childProcess.fork;
function PipeToChannel (options) { function PipeToChannel (options) {
this.fork = null; this.fork = null;
@ -16,7 +14,7 @@ function (Nc, childProcess) {
this.users = []; this.users = [];
try { try {
this.fork = fork('channel.js' this.fork = childProcess.fork('channel.js'
/*, { /*, {
execArgv: ['--debug=5859'] execArgv: ['--debug=5859']
}*/ }*/

218
scripts/optimize.js Normal file
View file

@ -0,0 +1,218 @@
/*
* This is supposed to be a code optimizer.
*
* usage:
* node scripts/optimize.js
*
* based on https://developers.google.com/speed/articles/optimizing-javascript
* I wanted to automatically replace properties as discribed under "Initializing instance variables"
*
* So far it is the only thing this script does, but the potential for more is there.
* Also it does not (yet) write to any files, only outputs the results in the console.
*
* The script fully disasembles the entire codebase (with esprima) and reconstructs (via escodegen) it
* with a few optimisations unfortunately it loses ambiguous new lines and such, so that it might
* not be entirely usable as a code replacing script - it could perhaps be used as a compile script in
* production
*
* But it has also nice things as at will add semicolons everywhere automatically and will
* definately keep a solid indentation style for everything. Since it lacks a lot of extra
* \n newlines it looks quite cluttered though.
*
*/
var fs = require('fs');
var util = require('util');
var esprima = require('esprima');
var escodegen = require('escodegen');
var info = [];
var generatorOption = {
format: {
indent: {
style: ' ',
base: 0,
adjustMultilineComment: true//false
},
newline: '\n',
space: ' ',
json: false,
renumber: false,
hexadecimal: false,
quotes: 'single',
escapeless: false,
compact: false,
parentheses: true,
semicolons: true,
safeConcatenation: true
},
moz: {
starlessGenerator: false,
parenthesizedComprehensionBlock: false,
comprehensionExpressionStartsWithAssignment: false
},
parse: null,
comment: true,
sourceMap: undefined,
sourceMapRoot: null,
sourceMapWithCode: false,
file: undefined,
directive: false,
verbatim: undefined
};
function readdir (path) {
var filesNames = fs.readdirSync(path)
for (var i = 0; i < filesNames.length; i++) {
var fileName = filesNames[i];
var fullPath = path + "/" + fileName;
if(path == "app/Lib/Vendor"){
continue;
}
if(fileName.indexOf(".js") == -1) {
var stats = fs.lstatSync(fullPath);
if (stats.isDirectory()) {
readdir(fullPath);
}
continue;
}
readFile(path, fileName);
};
}
function readFile (path, fileName) {
//console.log("+++++ " + moduleName + " ++++++");
var contents = fs.readFileSync(path + "/" + fileName);
contents = contents.toString();
optimize(path, fileName, contents);
}
function optimize (path, fileName, contents) {
var fullPath = path + "/" + fileName;
var moduleName = fileName.split(".js").join("");
var tree = esprima.parse(contents);
// find moduleId from return statement on module level
var module = tree.body[0].expression.arguments[1].body.body;
var moduleId = findModuleId(module);
if (!moduleId) {
info.push("could not find moduleId in: " + fullPath);
return;
}
if (moduleId == "Parent") {
info.push("not optimizing empty module (returning Parent) in: " + fullPath);
return;
}
// find constructor
var constructorPosition = findConstructorPosition(module, moduleId);
if (constructorPosition === false) {
info.push("could not find constructor in: " + fileName)
return;
}
var constructor = module[constructorPosition];
transformProps(tree, moduleId, constructor, constructorPosition);
console.log(escodegen.generate(tree, generatorOption));
}
function findModuleId (module) {
var moduleId = false;
for (var j = 0; j < module.length; j++) {
var expression = module[j];
//console.log(util.inspect(expression, { showHidden: true, depth: 4 }));
if (expression.type == "ReturnStatement") {
if(expression.argument.type == "Identifier") {
// for return Module;
moduleId = expression.argument.name;
break;
} else if (expression.argument.type == "NewExpression") {
// for return new Module;
moduleId = expression.argument.callee.name;
break;
} else {
info.push("Unexpected return type at module level. " + fullPath)
}
}
}
return moduleId;
};
function findConstructorPosition (module, moduleId) {
for (var j = 0; j < module.length; j++) {
var expression = module[j];
if (expression.type == "FunctionDeclaration" && expression.id.name == moduleId) {
return j;
}
}
return false;
}
function transformProps (tree, moduleId, constructor, constructorPosition) {
var props = [];
for (var k = constructor.body.body.length - 1; k >= 0; k--) {
var line = constructor.body.body[k];
if(line.expression
&& line.expression.type == "AssignmentExpression"
&& line.expression.operator == "="
&& line.expression.left.type == "MemberExpression"
&& line.expression.left.object.type == "ThisExpression"
&& line.expression.right.type == "Literal") {
// remove "this" properties with with value type from constructor
constructor.body.body.splice(k, 1);
//console.log(util.inspect(line, { showHidden: true, depth: 4 }));
props.push({
name: line.expression.left.property.name,
value: line.expression.right.value,
raw: line.expression.right.raw
});
}
};
// generate prototype properties
for (var l = 0; l < props.length; l++) {
var attributes = props[l];
var prop = { type: 'ExpressionStatement',
expression:
{ type: 'AssignmentExpression',
operator: '=',
left:
{ type: 'MemberExpression',
computed: false,
object:
{ type: 'MemberExpression',
computed: false,
object: { type: 'Identifier', name: moduleId },
property: { type: 'Identifier', name: 'prototype' } },
property: { type: 'Identifier', name: attributes.name } },
right: { type: 'Literal', value: attributes.value, raw: attributes.raw } } }
// place property after constructor
tree.body[0].expression.arguments[1].body.body.splice(constructorPosition+1, 0, prop);
};
}
readdir("app");
console.log(info)

125
scripts/optimize_.js Normal file
View file

@ -0,0 +1,125 @@
/*
* First version of the optimizer, relying completely on regular expressions
*
* it grabs the code as text and just executes the outermost function (module level)
* therefore it would not execute any real code, only setup the prototype functinos
* and the constructor
*
* since some modules use "return new Module();" to create a singleton, I added
* a mechanism to remove the "new" keyword and get the same kind of non-executing behaviour
*
* the trial failed because i could not replace the old constructor with the new one
* with simple replace algorithms because of whitespace differences
*
* Spits out some small statistics at the end, which is quite nice
*/
var fs = require('fs');
var successful = [];
var canceled = [];
var noconstruct = [];
var repaired = [];
function readdir (path) {
var filesNames = fs.readdirSync(path)
for (var i = 0; i < filesNames.length; i++) {
var fileName = filesNames[i];
var newPath = path + "/" + fileName;
if(path == "app/Lib/Vendor"){
continue;
}
if(fileName.indexOf(".js") == -1) {
var stats = fs.lstatSync(newPath);
if (stats.isDirectory()) {
readdir(newPath);
}
continue;
}
var moduleName = fileName.split(".js").join("");
var contents = fs.readFileSync(newPath);
contents = contents.toString();
// remove define construct around module, just get the module function
contents = contents.replace(/define\(\[[^\]]*\],\s*([\s\S]*)\);/, '$1');
// remove new from last return / disable singletons (eg. return new NotificationCenter;)
var before = contents;
contents = contents.replace(/([\s\S]*)return new ([a-zA-Z0-9]*)\s*\(?.*\);/, '$1return $2;');
if (contents != before){
repaired.push(moduleName);
}
eval("var module = " + contents);
try {
// test run, to get possible exceptions
var Parent = function(){};
var constructor = module(Parent);
if (typeof constructor == 'object') {
noconstruct.push(newPath);
continue;
}
//var optimizedModule = optimize(moduleName, module);
//console.log(optimizedModule);
successful.push(newPath);
} catch (e) {
//console.log(e) // see whats making it cancel
canceled.push(newPath);
}
};
}
function optimize(moduleName, module) {
/*
var better = module.toString();
var Parent = function(){};
var constructor = module(Parent).toString();
var regex = /^\s*this\.(.*) = (.*)\n?/mig;
var props = [];
do {
match = regex.exec(constructor);
if(match) {
props.push(moduleName + ".prototype." + match[1] + " = " + match[2]);
}
} while (match != null);
// remove original this.prop
constructor = constructor.replace(regex, '');
// add prototype variables at bottom of constructor
if (props.length > 0) {
constructor = constructor + "\n\n" + props.join("\n");
}
//constructor = constructor.replace("function " + moduleName + "(", "function " + moduleName + " (");
*/
return "";
}
readdir("app");
console.log("- Successful:", successful.length)
console.log("- Canceled:", canceled.length)
console.log("- No Constructor:", noconstruct.length)
console.log("- Repaired Singletons:", repaired.length)
console.log("canceled:", canceled)
console.log("no constructor:", noconstruct)
//console.log("successful:", successful)