Hi Gordon, I think it is inappropriate to discuss BuckleScript performances on this mailing list (people may feel unhappy about this), if you are interested, we can discuss on BuckleScript github issues(I will create a mailing list too). A minor comment: > As Elm does not have mutable linear arrays, for the big_uint functions I created a Native JS based library into which I just inserted the same JS code as created by the BS compiler for fairness; other than that it uses the same algorithm as the BS code.
This is seriously biased, it is similar to when benchmark the perf of Python against JS, Python users *rewrite the hot function *in C and call it from Python due to the incapability of Python. On Thu, Jan 26, 2017 at 4:31 AM, GordonBGood <[email protected]> wrote: > On Wednesday, 25 January 2017 19:25:40 UTC+7, Bob Zhang wrote: >> >> I cannot help replying when I see some inexact arguments... elm is a >> reasonably fast language, I think it might run even faster than purescript, >> enjoy your work! > > > I think Elm and PureScript might run at about the same speed plus/minus, > but ran into problems trying to use PureScript Lazy List Libraries. I've > stopped working with it because although it is about as powerful and type > safe as Haskell/GHCJS, it seemed to be overkill as an alternative to Elm > and it seemed that it would carry quite an overhead in library functions > even reduced for production. > > Here's a problem I know you will find interesting as it definitely applies > to BuckleScript: I've been trying my functional benchmarks across > different browsers since it seems there is such a range of performance for > the same code output on different JS engines. I expected BuckleScript to > be very consistent across browsers, and indeed it is between the latest > versions of Chrome and Edge, running just a little slower on Edge than on > Chrome as expected. However, the output BuckleScript JS code runs over > twice as slow as either of these on Firefox and in fact runs slower than > the Elm output for the same algorithm when also run on FireFox also by > about a factor of two. > > I'll post the full BuckleScript test code here for ready reference and so > you can copy and paste it to try it, as follows: > > type big_uint = int array > > external copy_array : 'a array -> 'a array = > "slice" [@@bs.send] > > external int2str : int -> string = "toString" [@@bs.send] > > external preadd_array : 'a array -> 'a -> unit = > "unshift" [@@bs.send] > > let zero_big_uint = [|0|] > > let one_big_uint = [|1|] > > let lt_big_uint (bu : big_uint) (othr : big_uint) = > let lenbu = Array.length bu in > let lenothr = Array.length othr in > if lenbu <> lenothr then (if lenbu < lenothr then true else false) else > let rtn = ref false in > let i = ref 0 in > while not !rtn && !i < lenbu do > let v1 = bu.(!i) in > let v2 = othr.(!i) in > let s1 = v1 land 0x80000000 in > let s2 = v2 land 0x80000000 in > i := !i + 1; > rtn := > if s1 <> s2 then ( (* remember negative signs are neg numbers!!! *) > i := lenbu; if s1 > s2 then true else false ) else > if v1 <> v2 then ( > i := lenbu; if v1 < v2 then true else false ) else false; > done; > !rtn > > > (* works only for 2 to 5 incl. *) > let mul_big_uint_byint (bu : big_uint) (m : int) = > let odd = (m land 1) <> 0 in > let shft = (m lsr 1) land 3 in > let cshft = 32 - shft in > let msk = (1 lsl shft) - 1 in > let mbu = copy_array bu in > let strt = Array.length bu - 1 in > let cry = ref ((if odd then mbu.(strt) else 0) land msk) in > for i = strt downto 0 do > let v = mbu.(i) in > let x = if i > 0 then mbu.(i - 1) else 0 in > let mlt = (v lsr shft) + (x lsl cshft) in > let p = (if odd then mlt else 0) + v in > let ps = p lsl shft in > let pc = ps + !cry in > (*Js.log !cry;*) > cry := (((if odd then > (mlt land v) lor ((mlt lxor v) land (p lxor -1)) > else 0) lsr 31) lsl shft) + > ((ps land (pc lxor -1)) lsr 31) + > (p lsr cshft); > mbu.(i) <- pc; > done; > (*Js.log !cry;*) > if !cry <> 0 then preadd_array mbu !cry; > mbu > > let string_of_big_uint bu = > let os = ref "" in > let mbu = copy_array bu in > let lng = Array.length bu - 1 in > let strt = ref 0 in > while !strt <= lng do > let rem = ref 0. in > for i = !strt to lng do > let v = > let x = float_of_int mbu.(i) in > if x >= 0. then x else 4294967296. +. x in > let dvd = !rem *. 4294967296. +. v in > let q = floor (dvd /. 10.) in > rem := dvd -. q *. 10.; > mbu.(i) <- int_of_float q; > done; > os := (!rem |> int_of_float |> int2str) ^ !os; > while !strt <= lng && mbu.(!strt) == 0 do > strt := !strt + 1; > done; > done; > !os > > type 'a lazy_list = > | EmptyLL > | ConsLL of 'a * 'a lazy_list Lazy.t > > let hammings() = > let rec merge a b = > match a, b with > | EmptyLL, b -> b > | a, EmptyLL -> a > | ((ConsLL (ahd, atl)) as a), ((ConsLL (bhd, btl)) as b) -> > (*analyze1 ahd bhd (lt_big_uint ahd bhd);*) > if lt_big_uint ahd bhd then > ConsLL (ahd, lazy (merge (Lazy.force atl) b)) > else ConsLL (bhd, lazy (merge a (Lazy.force btl))) in > let smult m s = > let rec smlt = function > | EmptyLL -> EmptyLL > | (ConsLL (hd, tl)) -> > (*analyze m hd (mul_big_uint_byint hd m);*) > ConsLL (mul_big_uint_byint hd m, > lazy (smlt (Lazy.force tl))) in smlt s in > let u s n = > let r = ref EmptyLL in > r := smult n (ConsLL ([|1|], lazy (!r))); > if s != EmptyLL then r := merge s !r; !r in > ConsLL ([|1|], lazy ([| 5; 3; 2 |] |> Array.fold_left u EmptyLL)) > > let rec ll_nth n ll = > match ll with > | EmptyLL -> None > | (ConsLL (hd, tl)) -> > if n <= 1 then Some hd > else ll_nth (n - 1) (Lazy.force tl) > > let find_nth_hamming n = > match ll_nth n (hammings()) with > | None -> "Ran out of values!!" > | Some v -> string_of_big_uint v > > let () = > let os = ref "" in > let hmgs = ref (hammings()) in > for i = 1 to 20 do > let ConsLL (hd, tl) = !hmgs in > os := !os ^ (string_of_big_uint hd) ^ " "; > hmgs := Lazy.force tl > done; > Js.log !os; > Js.log (find_nth_hamming 1691); > > let strt = now() in > let rslt = find_nth_hamming 1000000 in > let elpsd = now() -. strt in > > Js.log ("Got " ^ rslt ^ " in " ^ (string_of_float elpsd)) > > A few words of explanation about the code: it generates a lazy list > sequence of all the Hamming (Smooth 5 - all the cross multiples of the > prime numbers 2, 3, and 5 plus the start number 1) numbers using a purely > functional algorithm similar to how one might do the same thing in > Haskell. The timing benchmark takes the millionth number in this sequence, > which is a huge multi-precision integer of 84 digits - > 519312780448388736089589843750000000000000000000000000000000000000000000000000000000. > Since these languages don't have a built-in multi-precision library and > even if there were a library it would be overkill since all we need is > comparison, multiplication by the small integers (2, 3, and 5 for 5 Smooth) > and final output of the result as a long integer, i just wrote these > operators myself, with the multiply operation faster than many libraries > anyway due to the minimal requirements. The big_uint (unsigned) type is > represented as a big-endian JS array of Int's which grows as necessary as > the precision increases. The `hammings` algorithm is not the classic > Djikstra method but has been modified to eliminate duplicate operations (2 > times 3 versus 3 times 2 etc.). The rest of the code is pretty well self > explanatory. > > For results, on my Intel Skylake CPU running at 3.6 GHz, the BuckleScript > output takes about 3.5 seconds whereas it runs at about 1.2 seconds on > Chrome and about 1.5 seconds on Edge. > > For comparison's sake, I have attached a zip file of the equivalent in an > Elm project, which runs at about 1.8 seconds on Firefox, about 1.6 seconds > on Edge, but distressingly it runs at over 6 seconds on Chrome five times > slower. This file also includes the PrimesTreeFolding module which runs > only a little slower than BS on Chrome, but much more slowly on Edge this > time (haven't looked into that yet) - I haven't tried this on Firefox - may > or not be germane to the discrepancy in this post. > > As Elm does not have mutable linear arrays, for the big_uint functions I > created a Native JS based library into which I just inserted the same JS > code as created by the BS compiler for fairness; other than that it uses > the same algorithm as the BS code. One difference is that the way the > current elm-lang/lazy library works with Elm as it is much different from > that of OCaml/BS; I suspect that may be where the slowdown on Chrome comes > about - I plan to trace that down myself by gradually step-by-step forcing > the lazy implementation to be like that of BS; there is also a possibility > that some of the slowdown is due to multi-parametric union types rather > than OCaml's single parameter ones, and I will refactor to try that as well. > > Even at that, the Elm code runs about twice as fast as the BS code on > Firefox, although slightly slower than BS on Edge and much slower than the > BS code on Chrome (working on that). > > Anyway, it would be most interesting to hear your views on why the wide > variations and inconsistencies in speed across the different languages and > browsers. > > -- > 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.
