Skip to content
This repository has been archived by the owner on Jul 3, 2019. It is now read-only.

Commit

Permalink
Further small speed increases in injector, gaining another ~20% or so.
Browse files Browse the repository at this point in the history
Specifically, turned array of injection points into a linked list and changed method (and ctor) parameter values gathering to reuse one array instance instead of creating and discarding a new instance for each injection.
  • Loading branch information
tschneidereit committed Oct 28, 2011
1 parent 8d93c7a commit fae9488
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 132 deletions.
35 changes: 26 additions & 9 deletions src/org/swiftsuspenders/DescribeTypeJSONReflector.as
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,15 @@ package org.swiftsuspenders
gatherMethodParameters(parameters, parameterNames));
}

public function addFieldInjectionPointsToList(injectionPoints : Array) : void
public function addFieldInjectionPointsToList(
lastInjectionPoint : InjectionPoint) : InjectionPoint
{
gatherFieldInjectionPoints(_traits.accessors, injectionPoints);
gatherFieldInjectionPoints(_traits.variables, injectionPoints);
lastInjectionPoint = gatherFieldInjectionPoints(_traits.accessors, lastInjectionPoint);
return gatherFieldInjectionPoints(_traits.variables, lastInjectionPoint);
}

public function addMethodInjectionPointsToList(injectionPoints : Array) : void
public function addMethodInjectionPointsToList(
lastInjectionPoint : InjectionPoint) : InjectionPoint
{
for each (var method : Object in _traits.methods)
{
Expand All @@ -123,11 +125,16 @@ package org.swiftsuspenders
var optional : Boolean = extractOptionalFlag(injectParameters);
var parameterNames : Array = extractMappingName(injectParameters);
var parameters : Array = gatherMethodParameters(method.parameters, parameterNames);
injectionPoints.push(new MethodInjectionPoint(method.name, parameters, optional));
var injectionPoint : MethodInjectionPoint =
new MethodInjectionPoint(method.name, parameters, optional);
lastInjectionPoint.next = injectionPoint;
lastInjectionPoint = injectionPoint;
}
return lastInjectionPoint;
}

public function addPostConstructMethodPointsToList(injectionPoints : Array) : void
public function addPostConstructMethodPointsToList(
lastInjectionPoint : InjectionPoint) : InjectionPoint
{
const postConstructMethodPoints : Array = [];
for each (var method : Object in _traits.methods)
Expand All @@ -144,13 +151,19 @@ package org.swiftsuspenders
if (postConstructMethodPoints.length > 0)
{
postConstructMethodPoints.sortOn('order', Array.NUMERIC);
injectionPoints.push.apply(injectionPoints, postConstructMethodPoints);
for each (var injectionPoint : InjectionPoint in postConstructMethodPoints)
{
lastInjectionPoint.next = injectionPoint;
lastInjectionPoint = injectionPoint;
}
}
return lastInjectionPoint;
}


//---------------------- Private / Protected Methods ----------------------//
private function gatherFieldInjectionPoints(fields : Object, injectionPoints : Array) : void
private function gatherFieldInjectionPoints(
fields : Object, lastInjectionPoint : InjectionPoint) : InjectionPoint
{
for each (var field : Object in fields)
{
Expand All @@ -163,8 +176,12 @@ package org.swiftsuspenders
var optional : Boolean = extractOptionalFlag(injectParameters);
var config : InjectionPointConfig =
new InjectionPointConfig(field.type, mappingName, optional);
injectionPoints.push(new PropertyInjectionPoint(config, field.name));
var injectionPoint : PropertyInjectionPoint =
new PropertyInjectionPoint(config, field.name);
lastInjectionPoint.next = injectionPoint;
lastInjectionPoint = injectionPoint;
}
return lastInjectionPoint;
}

private function gatherMethodParameters(parameters : Array, parameterNames : Array) : Array
Expand Down
31 changes: 23 additions & 8 deletions src/org/swiftsuspenders/DescribeTypeReflector.as
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ package org.swiftsuspenders
return new ConstructorInjectionPoint(parameters);
}

public function addFieldInjectionPointsToList(injectionPoints : Array) : void
public function addFieldInjectionPointsToList(
lastInjectionPoint : InjectionPoint) : InjectionPoint
{
for each (var node : XML in _currentFactoryXML.*.
(name() == 'variable' || name() == 'accessor').metadata.(@name == 'Inject'))
Expand All @@ -113,23 +114,32 @@ package org.swiftsuspenders
node.arg.(@key == 'name').attribute('value'),
getOptionalFlagFromXMLNode(node));
var propertyName : String = node.parent().@name;
injectionPoints.push(new PropertyInjectionPoint(config, propertyName));
var injectionPoint : PropertyInjectionPoint =
new PropertyInjectionPoint(config, propertyName);
lastInjectionPoint.next = injectionPoint;
lastInjectionPoint = injectionPoint;
}
return lastInjectionPoint;
}

public function addMethodInjectionPointsToList(injectionPoints : Array) : void
public function addMethodInjectionPointsToList(
lastInjectionPoint : InjectionPoint) : InjectionPoint
{
for each (var node : XML in _currentFactoryXML.method.metadata.(@name == 'Inject'))
{
const nameArgs : XMLList = node.arg.(@key == 'name');
const parameters : Array =
gatherMethodParameters(node.parent().parameter, nameArgs);
injectionPoints.push(new MethodInjectionPoint(
node.parent().@name, parameters, getOptionalFlagFromXMLNode(node)));
var injectionPoint : MethodInjectionPoint = new MethodInjectionPoint(
node.parent().@name, parameters, getOptionalFlagFromXMLNode(node));
lastInjectionPoint.next = injectionPoint;
lastInjectionPoint = injectionPoint;
}
return lastInjectionPoint;
}

public function addPostConstructMethodPointsToList(injectionPoints : Array) : void
public function addPostConstructMethodPointsToList(
lastInjectionPoint : InjectionPoint) : InjectionPoint
{
const postConstructMethodPoints : Array = [];
for each (var node : XML in
Expand All @@ -141,9 +151,14 @@ package org.swiftsuspenders
}
if (postConstructMethodPoints.length > 0)
{
postConstructMethodPoints.sortOn("order", Array.NUMERIC);
injectionPoints.push.apply(injectionPoints, postConstructMethodPoints);
postConstructMethodPoints.sortOn('order', Array.NUMERIC);
for each (var injectionPoint : InjectionPoint in postConstructMethodPoints)
{
lastInjectionPoint.next = injectionPoint;
lastInjectionPoint = injectionPoint;
}
}
return lastInjectionPoint;
}

//---------------------- Private / Protected Methods ----------------------//
Expand Down
31 changes: 14 additions & 17 deletions src/org/swiftsuspenders/Injector.as
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ package org.swiftsuspenders

import org.swiftsuspenders.injectionpoints.InjectionPoint;
import org.swiftsuspenders.injectionpoints.InjectionPointConfig;
import org.swiftsuspenders.utils.ClassDescription;
import org.swiftsuspenders.utils.ClassDescriptor;
import org.swiftsuspenders.utils.SsInternal;
import org.swiftsuspenders.utils.getConstructor;
Expand Down Expand Up @@ -95,28 +94,27 @@ package org.swiftsuspenders
* This restriction is in place to prevent accidential changing of rules in ancestor
* injectors where only the child's response is meant to be altered.
*
* @param dependency The dependency to return the mapped rule for
* @param type The dependency to return the mapped rule for
* @return The rule mapped to the specified dependency class
* @throws InjectorError when no rule was found for the specified dependency
*/
public function getRule(dependency : Class) : InjectionRule
public function getRule(type : Class) : InjectionRule
{
var rule : InjectionRule = _mappings[dependency];
var rule : InjectionRule = _mappings[type];
if (!rule)
{
throw new InjectorError('Error while retrieving an injector mapping: ' +
'No rule defined for dependency ' + getQualifiedClassName(dependency));
'No rule defined for dependency ' + getQualifiedClassName(type));
}
return rule;
}

public function injectInto(target : Object) : void
{
var injecteeDescription : ClassDescription =
var ctorInjectionPoint : InjectionPoint =
_classDescriptor.getDescription(getConstructor(target));

var injectionPoints : Array = injecteeDescription.injectionPoints;
applyInjectionPoints(target, injectionPoints);
applyInjectionPoints(target, ctorInjectionPoint.next);
}

public function getInstance(type : Class) : *
Expand Down Expand Up @@ -209,14 +207,13 @@ package org.swiftsuspenders

SsInternal function instantiateUnmapped(type : Class) : *
{
var typeDescription : ClassDescription = _classDescriptor.getDescription(type);
var injectionPoint : InjectionPoint = typeDescription.ctor;
if (!injectionPoint)
var ctorInjectionPoint : InjectionPoint = _classDescriptor.getDescription(type);
if (!ctorInjectionPoint)
{
throw new InjectorError("Can't instantiate interface " + getQualifiedClassName(type));
}
var instance : * = injectionPoint.applyInjection(type, this);
applyInjectionPoints(instance, typeDescription.injectionPoints);
var instance : * = ctorInjectionPoint.applyInjection(type, this);
applyInjectionPoints(instance, ctorInjectionPoint.next);
return instance;
}

Expand All @@ -229,13 +226,13 @@ package org.swiftsuspenders
return rule;
}

private function applyInjectionPoints(target : Object, injectionPoints : Array) : void
private function applyInjectionPoints(
target : Object, injectionPoint : InjectionPoint) : void
{
var length : int = injectionPoints.length;
for (var i : int = 0; i < length; i++)
while (injectionPoint)
{
var injectionPoint : InjectionPoint = injectionPoints[i];
injectionPoint.applyInjection(target, this);
injectionPoint = injectionPoint.next;
}
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/org/swiftsuspenders/Reflector.as
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ package org.swiftsuspenders
function endReflection() : void;

function getCtorInjectionPoint() : InjectionPoint;
function addFieldInjectionPointsToList(injectionPoints : Array) : void;
function addMethodInjectionPointsToList(injectionPoints : Array) : void;
function addPostConstructMethodPointsToList(injectionPoints : Array) : void;
function addFieldInjectionPointsToList(
lastInjectionPoint : InjectionPoint) : InjectionPoint;
function addMethodInjectionPointsToList(
lastInjectionPoint : InjectionPoint) : InjectionPoint;
function addPostConstructMethodPointsToList(
lastInjectionPoint : InjectionPoint) : InjectionPoint;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,23 @@ package org.swiftsuspenders.injectionpoints
{
var ctor : Class = Class(target);
var p : Array = gatherParameterValues(target, injector);
var result : Object;
//the only way to implement ctor injections, really!
switch (p.length)
{
case 0 : return (new ctor());
case 1 : return (new ctor(p[0]));
case 2 : return (new ctor(p[0], p[1]));
case 3 : return (new ctor(p[0], p[1], p[2]));
case 4 : return (new ctor(p[0], p[1], p[2], p[3]));
case 5 : return (new ctor(p[0], p[1], p[2], p[3], p[4]));
case 6 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5]));
case 7 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6]));
case 8 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]));
case 9 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]));
case 10 : return (new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]));
case 1 : result = new ctor(p[0]); break;
case 2 : result = new ctor(p[0], p[1]); break;
case 3 : result = new ctor(p[0], p[1], p[2]); break;
case 4 : result = new ctor(p[0], p[1], p[2], p[3]); break;
case 5 : result = new ctor(p[0], p[1], p[2], p[3], p[4]); break;
case 6 : result = new ctor(p[0], p[1], p[2], p[3], p[4], p[5]); break;
case 7 : result = new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6]); break;
case 8 : result = new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); break;
case 9 : result = new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8]); break;
case 10 : result = new ctor(p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9]); break;
}
return null;
p.length = 0;
return result;
}
}
}
4 changes: 4 additions & 0 deletions src/org/swiftsuspenders/injectionpoints/InjectionPoint.as
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ package org.swiftsuspenders.injectionpoints

public class InjectionPoint
{
//---------------------- Public Properties ----------------------//
public var next : InjectionPoint;


//---------------------- Public Methods ----------------------//
public function InjectionPoint()
{
Expand Down
21 changes: 16 additions & 5 deletions src/org/swiftsuspenders/injectionpoints/MethodInjectionPoint.as
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ package org.swiftsuspenders.injectionpoints
public class MethodInjectionPoint extends InjectionPoint
{
//---------------------- Private / Protected Properties ----------------------//
private static const _parameterValues : Array = [];

protected var _parameterInjectionConfigs : Array;
protected var _requiredParameters : int = 0;

Expand Down Expand Up @@ -42,13 +44,21 @@ package org.swiftsuspenders.injectionpoints

override public function applyInjection(target : Object, injector : Injector) : Object
{
var parameters : Array = gatherParameterValues(target, injector);
if (!parameters && _isOptional)
var p : Array = gatherParameterValues(target, injector);
if (!p && _isOptional)
{
return target;
}
var method : Function = target[_methodName];
method.apply(target, parameters);
switch (p.length)
{
case 0 : (target[_methodName] as Function)(); break;
case 1 : (target[_methodName] as Function)(p[0]); break;
case 2 : (target[_methodName] as Function)(p[0], p[1]); break;
case 3 : (target[_methodName] as Function)(p[0], p[1], p[2]); break;
default: (target[_methodName] as Function).apply(target, p);
}

p.length = 0;
return target;
}

Expand All @@ -57,7 +67,8 @@ package org.swiftsuspenders.injectionpoints
protected function gatherParameterValues(target : Object, injector : Injector) : Array
{
var length : int = _parameterInjectionConfigs.length;
var parameters : Array = new Array(length);
var parameters : Array = _parameterValues;
parameters.length = length;
for (var i : int = 0; i < length; i++)
{
var parameterConfig : InjectionPointConfig = _parameterInjectionConfigs[i];
Expand Down
28 changes: 0 additions & 28 deletions src/org/swiftsuspenders/utils/ClassDescription.as

This file was deleted.

14 changes: 7 additions & 7 deletions src/org/swiftsuspenders/utils/ClassDescriptor.as
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,25 @@ package org.swiftsuspenders.utils
: new DescribeTypeReflector();
}

public function getDescription(type : Class) : ClassDescription
public function getDescription(type : Class) : InjectionPoint
{
//get injection points or cache them if this target's class wasn't encountered before
return _descriptionsCache[type] ||= createDescription(type);
}


//---------------------- Private / Protected Methods ----------------------//
private function createDescription(type : Class) : ClassDescription
private function createDescription(type : Class) : InjectionPoint
{
_reflector.startReflection(type);
const ctorInjectionPoint : InjectionPoint = _reflector.getCtorInjectionPoint();
const injectionPoints : Array = [];
_reflector.addFieldInjectionPointsToList(injectionPoints);
_reflector.addMethodInjectionPointsToList(injectionPoints);
_reflector.addPostConstructMethodPointsToList(injectionPoints);
var lastInjectionPoint : InjectionPoint = ctorInjectionPoint;
lastInjectionPoint = _reflector.addFieldInjectionPointsToList(lastInjectionPoint);
lastInjectionPoint = _reflector.addMethodInjectionPointsToList(lastInjectionPoint);
lastInjectionPoint = _reflector.addPostConstructMethodPointsToList(lastInjectionPoint);
_reflector.endReflection();

return new ClassDescription(type, ctorInjectionPoint, injectionPoints);
return ctorInjectionPoint;
}
}
}
Loading

0 comments on commit fae9488

Please sign in to comment.