Skip to content

Commit

Permalink
fiber optimization
Browse files Browse the repository at this point in the history
  • Loading branch information
krestenkrab committed Dec 3, 2009
1 parent 1794372 commit a55449e
Show file tree
Hide file tree
Showing 8 changed files with 187 additions and 72 deletions.
10 changes: 9 additions & 1 deletion pom.xml
Expand Up @@ -23,6 +23,14 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins> </plugins>
</build> </build>
<dependencies> <dependencies>
Expand Down Expand Up @@ -52,4 +60,4 @@
<version>3.2</version> <version>3.2</version>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>
90 changes: 54 additions & 36 deletions src/kilim/java/kilim/Fiber.java
Expand Up @@ -42,7 +42,9 @@ public final class Fiber {
* One State object for each activation frame in the call hierarchy. * One State object for each activation frame in the call hierarchy.
*/ */
private State[] stateStack = new State[10]; private State[] stateStack = new State[10];

private Object[] selfStack = new Object[10];
private int[] pcStack = new int[10];

/* /*
* Index into stateStack and equal to depth of call hierarchy - 1 * Index into stateStack and equal to depth of call hierarchy - 1
*/ */
Expand All @@ -60,7 +62,9 @@ public final class Fiber {
/* /*
* Special marker state used by pause * Special marker state used by pause
*/ */
private static final int PAUSE_STATE_PC = 1;
private static final State PAUSE_STATE = new State(); private static final State PAUSE_STATE = new State();
private static final State EMPTY_STATE = new State();


/* /*
* Status indicators returned by down() * Status indicators returned by down()
Expand All @@ -85,10 +89,6 @@ public final class Fiber {
*/ */
private static final int PAUSING__HAS_STATE = 3; private static final int PAUSING__HAS_STATE = 3;


static {
PAUSE_STATE.pc = 1;
}

public Fiber(Task t) { public Fiber(Task t) {
task = t; task = t;
} }
Expand Down Expand Up @@ -152,33 +152,14 @@ public int up() {
return NOT_PAUSING__NO_STATE; return NOT_PAUSING__NO_STATE;
} else { } else {
stack[d] = null; // clean up stack[d] = null; // clean up
pc = cs.pc; pc = pcStack[d];
// if (debug) System.out.println("\nup(not pausing)" + this);; // if (debug) System.out.println("\nup(not pausing)" + this);;
// if (debug) ds(); // if (debug) ds();
cs.releaseTo(this);
return NOT_PAUSING__HAS_STATE; return NOT_PAUSING__HAS_STATE;
} }
} }
} }


private static final int STATE_POOL_SIZE = 10;
int pool_count = 0;
State[] pool = new State[STATE_POOL_SIZE];

public final State allocState()
{
if (pool_count==0) return new State();
return pool[--pool_count];
}

final void release(State s) {
if (pool_count != STATE_POOL_SIZE) {
pool[pool_count++] = s;
s.self = null;
}
}


public final Fiber begin() { public final Fiber begin() {
return down(); return down();
} }
Expand Down Expand Up @@ -219,7 +200,7 @@ public Fiber down() {
} else { } else {
State s = stateStack[d]; State s = stateStack[d];
curState = s; curState = s;
pc = (s == null) ? 0 : s.pc; pc = (s == null) ? 0 : pcStack[d];
} }
// if (debug) System.out.println("down:\n" + this); // if (debug) System.out.println("down:\n" + this);
// if (debug) ds(); // if (debug) ds();
Expand Down Expand Up @@ -262,16 +243,17 @@ static void ds() {
*/ */
public int upEx() { public int upEx() {
// compute new iStack. // compute new iStack.
int is = task.getStackDepth() - 2; // remove upEx and convert to 0-based index. final int is = task.getStackDepth() - 2; // remove upEx and convert to 0-based index.
State cs = stateStack[is]; State cs = stateStack[is];


for (int i = iStack; i >= is; i--) { for (int i = iStack; i >= is; i--) {
stateStack[i] = null; // release state stateStack[i] = null; // release state
selfStack[i] = null; // release state
} }


iStack = is; iStack = is;
curState = cs; curState = cs;
return (cs == null) ? 0 : cs.pc; return (cs == null) ? 0 : pcStack[is];
} }


/** /**
Expand All @@ -282,25 +264,60 @@ public int upEx() {
public Object getCallee() { public Object getCallee() {
assert stateStack[iStack] != PAUSE_STATE : "No callee: this state is the pause state"; assert stateStack[iStack] != PAUSE_STATE : "No callee: this state is the pause state";
assert stateStack[iStack] != null : "Callee is null"; assert stateStack[iStack] != null : "Callee is null";
return stateStack[iStack + 1].self; return selfStack[iStack + 1];
} }


private State[] ensureSize(int newsize) { private void ensureSize(int newsize) {
// System.out.println("ENSURE SIZE = " + newsize); // System.out.println("ENSURE SIZE = " + newsize);
int len = stateStack.length;

State[] newStack = new State[newsize]; State[] newStack = new State[newsize];
System.arraycopy(stateStack, 0, newStack, 0, stateStack.length); System.arraycopy(stateStack, 0, newStack, 0, len);
stateStack = newStack; stateStack = newStack;
return newStack;
} Object[] newSelfStack = new Object[newsize];
System.arraycopy(selfStack, 0, newSelfStack, 0, len);
selfStack = newSelfStack;

int[] newPCStack = new int[newsize];
System.arraycopy(pcStack, 0, newPCStack, 0, len);
pcStack = newPCStack;
}


/** /**
* Called by the generated code before pausing and unwinding its stack * Called by the generated code before pausing and unwinding its stack
* frame. * frame.
* *
* @param state * @param state
*/ */
public void setState(State state) { public void setState(State state, Object self, int pc) {
stateStack[iStack] = state; stateStack[iStack] = state;
selfStack[iStack] = self;
pcStack[iStack] = pc;
isPausing = true;
// System.out.println("setState[" + + iStack + "] = " + this);
}

public void setState(State state, int pc) {
stateStack[iStack] = state;
selfStack[iStack] = null;
pcStack[iStack] = pc;
isPausing = true;
// System.out.println("setState[" + + iStack + "] = " + this);
}

public void setState(Object self, int pc) {
stateStack[iStack] = EMPTY_STATE;
selfStack[iStack] = self;
pcStack[iStack] = pc;
isPausing = true;
// System.out.println("setState[" + + iStack + "] = " + this);
}

public void setState(int pc) {
stateStack[iStack] = EMPTY_STATE;
selfStack[iStack] = null;
pcStack[iStack] = pc;
isPausing = true; isPausing = true;
// System.out.println("setState[" + + iStack + "] = " + this); // System.out.println("setState[" + + iStack + "] = " + this);
} }
Expand All @@ -311,9 +328,10 @@ void togglePause() {
// upto date. // upto date.


if (curState == null) { if (curState == null) {
setState(PAUSE_STATE); setState(PAUSE_STATE, PAUSE_STATE_PC);
} else { } else {
assert curState == PAUSE_STATE : "togglePause: Expected PAUSE_STATE, instead got: iStack == " + iStack + ", state = " + curState; assert curState == PAUSE_STATE :
"togglePause: Expected PAUSE_STATE, instead got: iStack == " + iStack + ", state = " + curState;
stateStack[iStack] = null; stateStack[iStack] = null;
isPausing = false; isPausing = false;
} }
Expand Down
11 changes: 2 additions & 9 deletions src/kilim/java/kilim/State.java
Expand Up @@ -25,13 +25,6 @@
*/ */


public class State { public class State {
public int pc; //public int pc;
public Object self; //public Object self;

/**
* @param fiber
*/
void releaseTo(Fiber fiber) {
fiber.release(this);
}
} }
70 changes: 51 additions & 19 deletions src/kilim/java/kilim/analysis/CallWeaver.java
Expand Up @@ -516,32 +516,41 @@ private void genSave(MethodVisitor mv, Label saveLabel) {
* the method weaver's list. This allows us to do a switch in the * the method weaver's list. This allows us to do a switch in the
* method's entry. * method's entry.
*/ */
if (stateClassName.equals(STATE_CLASS)) { boolean is_simple_state = stateClassName.equals(STATE_CLASS);

if (is_simple_state) {

loadVar(mv, TOBJECT, methodWeaver.getFiberVar()); loadVar(mv, TOBJECT, methodWeaver.getFiberVar());
mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "allocState", "()" + D_STATE);
if (!bb.flow.isStatic()) {
mv.visitInsn(ALOAD_0); // for state.self == this
}

int pc = methodWeaver.getPC(this);
if (pc < 6) {
mv.visitInsn(ICONST_0 + pc);
} else {
mv.visitIntInsn(BIPUSH, pc);
}

if (!bb.flow.isStatic()) {
methodWeaver.ensureMaxStack(3);
mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "(Ljava/lang/Object;I)V");
} else {
methodWeaver.ensureMaxStack(2);
mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "(I)V");
}


} else { } else {
mv.visitTypeInsn(NEW, stateClassName); mv.visitTypeInsn(NEW, stateClassName);
mv.visitInsn(DUP); // mv.visitInsn(DUP); //
// call constructor // call constructor
mv.visitMethodInsn(INVOKESPECIAL, stateClassName, "<init>", "()V"); mv.visitMethodInsn(INVOKESPECIAL, stateClassName, "<init>", "()V");
}
// save state in register // save state in register
int stateVar = allocVar(1); int stateVar = allocVar(1);
storeVar(mv, TOBJECT, stateVar); storeVar(mv, TOBJECT, stateVar);
// state.self = this if the current executing method isn't static
if (!bb.flow.isStatic()) {
loadVar(mv, TOBJECT, stateVar);
mv.visitInsn(ALOAD_0); // for state.self == this
mv.visitFieldInsn(PUTFIELD, STATE_CLASS, "self", D_OBJECT);
}
int pc = methodWeaver.getPC(this);
loadVar(mv, TOBJECT, stateVar); // state.pc
if (pc < 6) {
mv.visitInsn(ICONST_0 + pc);
} else {
mv.visitIntInsn(BIPUSH, pc);
}
mv.visitFieldInsn(PUTFIELD, STATE_CLASS, "pc", D_INT);


// First save bottom stack into state // First save bottom stack into state
int i = getNumBottom() - 1; int i = getNumBottom() - 1;
Expand Down Expand Up @@ -585,9 +594,32 @@ private void genSave(MethodVisitor mv, Label saveLabel) {
// Fiber.setState(state); // Fiber.setState(state);
loadVar(mv, TOBJECT, methodWeaver.getFiberVar()); loadVar(mv, TOBJECT, methodWeaver.getFiberVar());
loadVar(mv, TOBJECT, stateVar); loadVar(mv, TOBJECT, stateVar);
mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "("
+ D_STATE + ")V"); if (!bb.flow.isStatic()) {
mv.visitInsn(ALOAD_0); // for state.self == this
}

int pc = methodWeaver.getPC(this);
if (pc < 6) {
mv.visitInsn(ICONST_0 + pc);
} else {
mv.visitIntInsn(BIPUSH, pc);
}

if (!bb.flow.isStatic()) {
methodWeaver.ensureMaxStack(4);
mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "("
+ D_STATE + "Ljava/lang/Object;I)V");
} else {
methodWeaver.ensureMaxStack(3);
mv.visitMethodInsn(INVOKEVIRTUAL, FIBER_CLASS, "setState", "("
+ D_STATE + "I)V");
}

releaseVar(stateVar, 1); releaseVar(stateVar, 1);
}


// Figure out the return type of the calling method and issue the // Figure out the return type of the calling method and issue the
// appropriate xRETURN instruction // appropriate xRETURN instruction
retType = TypeDesc.getReturnTypeDesc(bb.flow.desc); retType = TypeDesc.getReturnTypeDesc(bb.flow.desc);
Expand Down
6 changes: 0 additions & 6 deletions src/kilim/java/kilim/analysis/ClassWeaver.java
Expand Up @@ -190,12 +190,6 @@ String createStateClass(ValInfoList valInfoList) {
ClassWriter cw = new ClassWriter(0); ClassWriter cw = new ClassWriter(0);
cw.visit(V1_1, ACC_PUBLIC | ACC_FINAL, className, null, "kilim/State", null); cw.visit(V1_1, ACC_PUBLIC | ACC_FINAL, className, null, "kilim/State", null);


MethodVisitor mv = cw.visitMethod(0, "releaseTo", "(Lkilim/Fiber;)V" , null, null);
mv.visitCode();
mv.visitInsn(RETURN);
mv.visitMaxs(1, 2);
mv.visitEnd();

// Create default constructor // Create default constructor
// <init>() { // <init>() {
// super(); // call java/lang/Object.<init>() // super(); // call java/lang/Object.<init>()
Expand Down
69 changes: 69 additions & 0 deletions src/main/erl/fib.erl
@@ -0,0 +1,69 @@
-module(fib).
-export([fibo/1, fibo2/1, fibo3/1, print_nfibos/2, main/0, runLength/2, main2/0]).

%% print fibo arg. and result, with function as parameter

print_nfibos( N, FiboFunc) -> printfibos( N, FiboFunc, 0).

printfibos( 0, FiboFunc, N) -> %% last recursion
Res = FiboFunc(N),
io:format("~w ~w~n", [N, Res]) ;

printfibos( Iter, FiboFunc, N) when Iter > 0 ->
Res = FiboFunc(N),
io:format("~w ~w~n", [N, Res]),
printfibos( Iter -1, FiboFunc, N +1).



fibo(0) -> 0 ;
fibo(1) -> 1 ;
fibo(N) when N > 0 -> fibo(N-1) + fibo(N-2) .


fibo2_tr( 0, Result, _Next) -> Result ; %% last recursion output

fibo2_tr( Iter, Result, Next) when Iter > 0 -> fibo2_tr( Iter -1, Next, Result + Next) .

fibo2( N) -> fibo2_tr( N, 0, 1) .


fibo3(N) ->
{Fib, _} = fibo3(N, {1, 1}, {0, 1}),
Fib.

fibo3(0, _, Pair) -> Pair;
fibo3(N, {Fib1, Fib2}, Pair) when N rem 2 == 0 ->
SquareFib1 = Fib1*Fib1,
fibo3(N div 2, {2*Fib1*Fib2 - SquareFib1, SquareFib1 + Fib2*Fib2}, Pair);
fibo3(N, {FibA1, FibA2}=Pair, {FibB1, FibB2}) ->
fibo3(N-1, Pair, {FibA1*FibB2 + FibB1*(FibA2 - FibA1), FibA1*FibB1 + FibA2*FibB2}).


time(F,N) ->
{Time,_Res} = timer:tc(fib,F,[N]),
io:format("~w,~w,~w~n", [F,N,Time]).

tlength(L) -> tlength(L,0).
tlength([_|T],Acc) -> tlength(T,Acc+1);
tlength([],Acc) -> Acc.

makeList(N) when N==0 -> [];
makeList(N) -> [N,makeList(N-1)].

runLength(_,N) when N==0 -> done;
runLength(L,N) -> tlength(L), runLength(L,N-1).

main() ->
List = makeList(2000),
io:format("time=~w~n", [timer:tc(fib,runLength,[List,1000000])]).

main2() ->
time(fibo3,10),
time(fibo3,100),
time(fibo3,1000),
time(fibo3,10000),
time(fibo3,100000),
time(fibo3,1000000).


0 comments on commit a55449e

Please sign in to comment.