Hi Gordon,
  As you can see, BuckleScript already did a very good good job here, of
course, there are still places for improvement. To write extremely high
performance code, you should avoid creating a closure in a tight loop, here
you can lift the `nxtc` into the toplevel, in the future, we will do this
inside the compiler. Lets take further discussions off the list -- Hongbo

On Wed, Jan 4, 2017 at 1:17 AM, GordonBGood <[email protected]> wrote:

> Hi Bob/Hongbo,
>
> I've run into my first speed problem with BuckleScript:  When it decides
> it needs to form a closure of captured free binding(s), it creates a
> "function returning a function" with the outer function's arguments being
> the current state of the "pure" captured bindings, and the inner returned
> function the actual closure code.  When this happens anywhere near an inner
> loop, the code gets very slow, although sometimes the compiler is smart
> enough to infer that the closure is not necessary is when the binding value
> is an argument of an enclosing function; however, this does not happen for
> local `let` bindings even when they are in the same scope as the
> callee/caller sites.
>
> For example, the following bit-packed Sieve of Eratosthenes sieves over a
> range and returns the bit packed array of found primes over that range
> (odds-only.  It runs about five times slower than using imperative code
> for/while loops (top of a quarter million).  Code is as follows:
>
> let soe_loop top =
>   if top < 3 then Array.make 0 0 else
>   let ndxlmt = (top - 3) lsr 1 in
>   let cmpsts = Array.make ((ndxlmt lsr 5) + 1) 0 in
>   for loop = 1 to 1000 do (* do it many times for timing *)
>     let pir = ref 0 in
>     while !pir <= ndxlmt do
>       let pi = !pir in
>       let p = pi + pi + 3 in
>       let rec nxtc ci =
>       if ci > ndxlmt then () else
>       let w = ci lsr 5 in
>       cmpsts.(w) <- cmpsts.(w) lor (1 lsl (ci land 31));
>       nxtc (ci + p) in
>       let si = (p * p - 3) lsr 1 in
>       if si > ndxlmt then pir := ndxlmt + 1 else (
>         if cmpsts.(pi lsr 5) land (1 lsl (pi land 31)) == 0 then
>           nxtc si
>   cmpsts
>
> where the outer `pi` loops are imperative and the inner `nxtc` loop is
> functional; this latter becomes the closure that captures the `p` value as
> you can see in the following generated JavaScript:
>
> function soe_loop(top) {
>   if (top < 3) {
>     return Caml_array.caml_make_vect(0, 0);
>   }
>   else {
>     var ndxlmt = ((top - 3 | 0) >>> 1);
>     var cmpsts = Caml_array.caml_make_vect((ndxlmt >>> 5) + 1 | 0, 0);
>     for(var loop = 1; loop <= 1000; ++loop){
>       var pir = 0;
>       while(pir <= ndxlmt) {
>         var pi = pir;
>         var p = (pi + pi | 0) + 3 | 0;
>         var nxtc = (function(p){
>         return function nxtc(_ci) {
>           while(true) {
>             var ci = _ci;
>             if (ci > ndxlmt) {
>               return /* () */0;
>             }
>             else {
>               var w = (ci >>> 5);
>               cmpsts[w] = cmpsts[w] | (1 << (ci & 31));
>               _ci = ci + p | 0;
>               continue ;
>
>             }
>           };
>         }
>         }(p));
>         var si = ((Caml_int32.imul(p, p) - 3 | 0) >>> 1);
>         if (si > ndxlmt) {
>           pir = ndxlmt + 1 | 0;
>         }
>         else {
>           if (!(cmpsts[(pi >>> 5)] & (1 << (pi & 31)))) {
>             nxtc(si);
>           }
>           pir = pi + 1 | 0;
>         }
>       };
>     }
>     return cmpsts;
>   }
> }
>
> As the compiler knows that the `p` value is pure, it should know that it
> can reference it without danger of it being in an unknown state, so there
> is no need for a cloaure, and if `nxtc` is not a closure then it can be
> inlined as usual.
>
> The same thing happens currently when all loops are functional.
>
> The back up work around is to use imperative code, but that's ugly.  I
> wonder if you have any suggestions to avoid the closure?
>
> Regards, Gordon
>
>>
>>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "Elm Discuss" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/
> topic/elm-discuss/Um7WIBTq9xU/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> For more options, visit https://groups.google.com/d/optout.
>



-- 
Regards
-- Hongbo Zhang

-- 
You received this message because you are subscribed to the Google Groups "Elm 
Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to