On Wed, 2007-02-14 at 00:18 -0500, Chris King wrote:
[]
This code appears to work:
////////////////////////////////////////////
#import <flx.flxh>
val n = 10;
proc worker(k:int, i: ischannel[int], o: oschannel[int]) {
print "Starting worker "; print k; endl;
forever {
var &x: int <- read i;
print "Worker "; print k; print " read "; print x; endl;
write(o, x + 1);
};
}
def var inp, val out = mk_ioschannel_pair[int] ();
proc spawner (k:int, i: ischannel[int]) {
if k < n do
def var i', var o' = mk_ioschannel_pair[int] ();
spawn_fthread { worker(k, i, o'); };
spawner(k+1, i');
else
inp = i;
done;
}
spawner(1,inp);
spawn_fthread { write(out,1000); };
spawn_fthread {
var &x : int <- read inp;
print "Final result "; print x; endl;
};
////////////////////////////////////////////
I get:
///////////////////////////////////////////
[EMAIL PROTECTED]:/work/felix/svn/felix/felix/trunk$ f
cheap-concurrency.flx
Starting worker 9
Starting worker 8
Starting worker 7
Starting worker 6
Starting worker 5
Starting worker 4
Starting worker 3
Starting worker 2
Starting worker 1
Worker 1 read 1000
Worker 2 read 1001
Worker 3 read 1002
Worker 4 read 1003
Worker 5 read 1004
Worker 6 read 1005
Worker 7 read 1006
Worker 8 read 1007
Worker 9 read 1008
Final result 1009
///////////////////////////////////////////
which is what I expected. The trick is that the
spawner() routine is (self-tail) recursive rather
than iterative, ensuring the values are all in
distinct stack frames which the spawned closures
can refer to.
I used this routine:
////////////////////////////////////////////
#import <flx.flxh>
val n = int(System::argv 1);
proc worker(k:int, i: ischannel[int], o: oschannel[int]) {
//print "Starting worker "; print k; endl;
forever {
var &x: int <- read i;
//print "Worker "; print k; print " read "; print x; endl;
write(o, x + 1);
};
}
def var inp, val out = mk_ioschannel_pair[int] ();
proc spawner (k:int, i: ischannel[int]) {
if k < n do
def var i', var o' = mk_ioschannel_pair[int] ();
spawn_fthread { worker(k, i, o'); };
spawner(k+1, i');
else
inp = i;
done;
}
spawner(1,inp);
spawn_fthread { write(out,1); };
spawn_fthread {
var &x : int <- read inp; print "Final result "; print x; endl;
};
/////////////////////////////////////////////
to do some real tests (the first run has to compile
the code .. after that it should be cached).
[EMAIL PROTECTED]:/work/felix/svn/felix/felix/trunk$ time f
cheap-concurrency.flx 500
Final result 500
real 0m0.965s
user 0m0.844s
sys 0m0.116s
[EMAIL PROTECTED]:/work/felix/svn/felix/felix/trunk$ time f
cheap-concurrency.flx 10000
Final result 10000
real 0m2.217s
user 0m2.088s
sys 0m0.112s
[EMAIL PROTECTED]:/work/felix/svn/felix/felix/trunk$ time f
cheap-concurrency.flx 20000
Final result 20000
real 0m11.472s
user 0m11.313s
sys 0m0.156s
[EMAIL PROTECTED]:/work/felix/svn/felix/felix/trunk$ time f
cheap-concurrency.flx 30000
Final result 30000
real 0m27.272s
user 0m26.894s
sys 0m0.256s
[EMAIL PROTECTED]:/work/felix/svn/felix/felix/trunk$ time f
cheap-concurrency.f lx 50000
Final result 50000
real 1m18.154s
user 1m16.541s
sys 0m0.448s
[EMAIL PROTECTED]:/work/felix/svn/felix/felix/trunk$ time f
cheap-concurrency.flx 100000
Final result 100000
real 5m6.856s
user 5m3.455s
sys 0m1.364s
It's not clear why the slowdown here: performance isn't linear.
Scheduling is O(1), so I don't expect this.
Note it is NOT the garbage collector: the collector() is not
being called: automatic calls are commented out in the
current driver code .. :)
--
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net
-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Felix-language mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language