Re: Change in semantics for some control flow operations
Jeremy Tregunna <[email protected]> Fri, 09 Dec 2011 17:16:16 -0600
| Newsgroups | gmane.comp.lang.io |
|---|---|
| Message-ID | <[email protected]> |
If I implemented those methods in C to compare, then yes we should. Since I reproduced foreach, I think that was a fair comparison. I didn't feel like having to submit a patch so people could test on their own having to recompile their VM to get a fair comparison (C vs C vs C); so instead, I gave 3 simple Io implementations that everyone could just paste into their REPL :) On 2011-12-09, at 5:02 PM, Steve Dekorte wrote: > > > To be fair, we should compare it to the C implementation of foreach, right? > > I get: > > 0.000341 for Date secondsToRun(lst foreach(1000000)) println > 0.019947 for Date secondsToRun(lst foreachNormal(1000000)) println > 0.018511 for Date secondsToRun(lst foreachContext(1000000)) println > 0.054686 for Date secondsToRun(lst foreachBlock(1000000)) println > > So ~60x slower. Though if we were going to do this, we'd implement the scoped version of foreach in C too. > It would be interesting to see the difference. I'm guessing 10x for a no op loop but maybe much less if it's looping on a calll to an Io defined method. > > I generally like the idea. What do you think about implementing it on control flow using blocks instead? > > On 2011-12-09 Fri, at 02:46 PM, Jeremy Tregunna wrote: >> >> A quick test, code below, results first: >> >> Normal foreach (the way we implement it now): 0.045998, 0.042344, 0.04463 >> With a single throwaway context: 0.041687, 0.044041, 0.042541 >> With a block: 0.129006, 0.134746, 0.133294 >> >> The above results are based on three runs, of the code below. As you can tell, it's a very trivial example (single arg form, didn't implement the other two and three arg forms for the sake of time): >> >> List foreachNormal := method( >> body := call argAt(0) >> for(i, 1, size, call sender doMessage(body)) >> ) >> >> List foreachContext := method( >> body := call argAt(0) >> ctx := call sender clone >> for(i, 1, size, body doInContext(ctx)) >> ) >> >> List foreachBlock := method( >> body := call argAt (0) >> blk := block setMessage(body) setScope(call sender) >> for(i, 1, size, blk call) >> ) >> >> Range; >> >> lst := 1 to(10000) asList >> Date secondsToRun(lst foreachNormal(1000000)) println >> Date secondsToRun(lst foreachContext(1000000)) println >> Date secondsToRun(lst foreachBlock(1000000)) println >> >> >> On 2011-12-09, at 4:30 PM, Steve Dekorte wrote: >> >>> >>> >>> Can you do a test to determine what the performance costs are? >>> >>> On 2011-12-08 Thu, at 06:43 AM, Jeremy Tregunna wrote: >>>> I want to propose a change in direction for the standard library foreach(), select(), and friends methods. I'll supply code, don't worry about that. >>>> >>>> Right now, how we go about doing things is once we're iterating, we set values in the calling context directly. This has obvious problems worse than shadowing, i.e., overwriting values we want and persisting after the foreach() has finished. Now at present, anyone hit by this problem will have renamed their identifiers when they got bad results, but this is rather confusing. Additionally, why should we leak these values? >>>> >>>> I'm proposing one of two solutions I think are a better fit: >>>> >>>> 1. Set up a block with the argument name(s) we want to set, the body we want to evaluate, and the proper scope to capture (the sender). Call that inside our main loop. >>>> 2. Create a separate isolated context outside the loop, set our value(s) in it inside the loop, a sk our body to doInContext with that context and the sender. This has a slight advantage performance wise in that we only create one context, as opposed to creating N locals with the block worst case (or recycling N locals depending on our environment). >>>> >>>> Now, this does have the negative use in that it breaks operational semantics of these methods at present if a user depends on this behaviour, but I'm ok with that; I'd consider that behaviour broken anyway. >>>> >>>> I think this should be done to all the standard library objects that support these types of constructs. Take some of the surprise out of using them. >>>> >>>> Regards, >>>> >>>> Jeremy Tregunna >>> >>> >>> >> >> Regards, >> >> Jeremy Tregunna >> < /div> >> >> >> >> > > > Regards, Jeremy Tregunna