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 <gordonbg...@gmail.com> 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
> elm-discuss+unsubscr...@googlegroups.com.
> 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 elm-discuss+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to