On Thursday, 26 January 2017 21:13:33 UTC+7, Bob Zhang wrote:
>
> 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).
>

Yes, Hongbo, I considered that, but since the subject of this thread is 
speed, and BuckleScript has been brought up many times as a speedy 
alternative to Elm including by yourself as author, I just wanted to show 
that all is not roses in BuckleScript land.  I have done some more work in 
this issue and am beginning to think that the choice of JS Array's as the 
base data representation in BuckleScript as opposed to JS Object/Records in 
Elm/Fable may not have been a good one for consistency of performance 
across browsers but wonder what you think it is:  it seems that Chrome V8 
optimizes relative JS Array performance much better than other browsers, 
especially Firefox, which may be what is reflected here.  I also re-ran the 
functional primes benchmark on Firefox and again found the BS version very 
slow, in this case about five times slower than Elm.  If you want to open 
up an alternate means of communication about this issue, I will be happy to 
contribute further as to BuckleScript development.  Perhaps an issue should 
be filed in the BuckleScript repo?

Now all is not roses in Elm land either, which IS the subject of this 
thread:  while as Robin Heggelund Hansen has pointed out, JS 
Objects/Records seem to be a fine efficient data representation across 
browsers, different browsers seem to do different quality jobs in interning 
the string tags, or at least Elms way of emitting them, with the Chrome way 
much more suited than that of FireFox or Edge (the worst) so that I believe 
that most of the performance issues I have in different browsers are due to 
this.  Of course, if the Elm back end were using the static type 
information that should be available to it (the actual subject of this 
thread), this this would not be a problem, as the use of any tag 
information could be minimized and reduced to identifying which of the set 
of union cases is in play.

What I have learned (and which BS does very well) is that no tags are 
actually needed or desired except for ADT's/tagged unions (that's why tag 
is in the name) *if type information is used*, and that while BS uses 
numeric indices for JS Array's, string/s/symbols with Object/Records are 
likely at least as good *as long as we help the JS engine do string 
interning* in order to get better speed consistency across browsers.  I 
will be writing more about this shortly as soon as I complete some more 
benchmarks.

Meanwhile, I now know why elm-lang/lazy is so slow on Chrome V8 when used 
in lazy lists:  they are implemented as nested functions, which sometimes 
get inlined but when not (as when part of lazy list definitions) are about 
50 times slower than Immediately Invoked Function Expressions (IIFE's) on 
Chrome V8.  This is a problem unique to Chrome V8, as new Firefox doesn't 
have a problem with nested functions at all, and they have a relatively 
minor cost in Edge.  The use of nested functions is a common problem across 
JS language transpilers (for instance Fable), and although BS has a 
different implementation of Lazy that doesn't use nested functions, it is 
the cause of the huge slowdown I pointed out earlier for embedded closures, 
for which BS does use nested functions.  Here is a link to some performance 
tests and data. <http://jsperf.com/iifes-vs-nested-functions/4>  I plan to 
re-write elm-lang/lazy to use IIFE's instead of nested functions, which 
should take care of the Elm speed discrepancy problem in Chrome.  While 
this is easily fixed for elm-lang/lazy because it is a library, it isn't so 
easy to fix for closures that are implemented as nested functions by the 
compiler itself; although they, too, can be "lifted" and implemented as 
IIFE's, this needs to be done by the compiler and not just a library.
 

>   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 benchmarking 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.
>

While I agree that using a compiled library function in interpreted Python 
to benchmark Python speed is a fallacy, both Elm and BS are compiled 
languages with the primary difference that Elm strictly enforces 
immutability of all data structures at the language level whereas OCaml/BS 
does not.  Now, I could have fairly easily used the current Elm Array type 
to implement the big_uint type and operators and it wouldn't have been that 
slow since this benchmark doesn't exceed the current Array linear sub-array 
size of 32 32-bit Int's (308 decimal digits), but what I really wanted to 
test was the lazy list function capabilities as to speed and not the 
overall current language limitations; thus, the shortcut to compare lazy 
lists like-with-like.

Again, the limitations of the current Elm Array can be overcome by 
providing a linear immutable IArray library module similar to the immutable 
IArray library module in Haskell without breaking the mandated external 
immutability of all data structures in Elm, and if that were available then 
the big_uint functions/operators could be written to be about the same 
speed as with BS; I am working on such a library module.  As I am sure you 
know, immutability is a blessing as to producing safe reliable code, but it 
can have a cost in performance as compared to using mutable data 
structures, which cost can be reduced by careful attention to how 
immutability is used.  All immutable structures go through a mutable stage 
while being constructed, and I am proposing to make type safe capabilities 
available to tap into while construction is going on, just as is done in 
Haskell.  By doing that, one can get close to mutable code speed but still 
using externally immutable IArray data structures, with the limitation that 
any algorithm taking advantage of this must batch array `set` operations so 
as to occur during (each) construction; individual `set' calls will be 
extremely slow and worse than using the Array tree structure of the current 
and proposed Array library modules.

-- 
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