News for hackers. Stuff that matters.
Re:Emacs-ng: Emacs with Deno runtime and TypeScript by vitus on Monday March 15, 2021 @06:53PM (#26470377)
EDIT: as pointed out, this is run with Guile 2.2, which is pre-JIT. Results to be posted later in this thread...

Okay.

    $ cat fib.scm
    (define (fibonacci n)
      (if (<= n 1)
          n
        (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
    (fibonacci 40)
    $ time guile fib.scm
    guile fib.scm  8.52s user 0.01s system 99% cpu 8.559 total
Node also uses V8.

    $ time node fib.js 
    node fib.js  1.29s user 0.01s system 100% cpu 1.296 total
But okay, you wanted deno.

    $ time deno run fib.js
    deno run fib.js  1.41s user 0.02s system 99% cpu 1.423 total
Meanwhile, using `emacs --script fib.elc` to evaluate byte-compiled (fib 40) takes about 32s. And `emacs --script fib.el` takes about 2x that, at 64s.

edit: for reference, the equivalent C code runs in 0.27s on my laptop.

edit edit: okay, okay, compiling the Guile code before running it speeds it up to an exciting 8.16s execution time, still about 6x slower than deno.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by eddieh on Monday March 15, 2021 @09:44PM (#26471904)
This got me curious about other Scheme implementations.

Chicken compiles to C

    $ csc fib.scm
    $ time ./fib

    real 0m8.461s
    user 0m8.383s
    sys  0m0.061s
Racket has a modern JIT

    $ cat fib.rkt 
    #lang racket
    (define (fibonacci n)
      (if (<= n 1)
          n
          (+ (fibonacci (- n 1)) (fibonacci (- n 2)))))
    (fibonacci 40)
    $ time racket fib.rkt
    102334155

    real 0m1.396s
    user 0m1.142s
    sys  0m0.127s
For reference

    $ sysctl -a | grep .brand_string
    machdep.cpu.brand_string: Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz
Re:Emacs-ng: Emacs with Deno runtime and TypeScript by taeric on Monday March 15, 2021 @10:39PM (#26472254)
This got me interested in other lisps, as well. Looks like sbcl gives (time (fib 40)) to be about 1.7 seconds on my machine. (Ryzen 5 3600x.)

For lulz, I clocked a dumb loop version.

    (defun fib (n)
        (loop repeat n
              for a = 1 then b
              for b = 1 then c
              for c = (+ a b)
              finally (return a)))
And... well, serves as an amusing reminder that tree recursion has its downsides. :D

Edit: I confess the speed of the loop got me curious and.... javascript has numeric overflow. That would be a hell of a surprise if you weren't expecting it.

Edit2: (I realize overflow isn't the right term, but it is amusing that I can calc the 10000th fib in elisp... not so much in javascript. And yes, even elisp falls over sooner than sbcl does.)

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by anthk on Tuesday March 16, 2021 @04:42AM (#26474287)
>And... well, serves as an amusing reminder that tree recursion has its downsides. :D

OFC I would rewrite that as a iterative form (and any Schemer here could :D), but here we are testing performance :D.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by taeric on Tuesday March 16, 2021 @10:10AM (#26476867)
Agreed. I didn't mean that necessarily as a criticism of anything. Just hard to have an intuition for just how much it slows down.

I suppose there is a bit of something in there about using the right algorithm. But I can understand picking one that will take time for comparing speed. I'm not sure either is really representative of work you expect an editor to do, though. Curse of benchmarks.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by vitus on Tuesday March 16, 2021 @04:56PM (#26482852)
The speed of the naive recursive fib scales with the number it computes, which is roughly 1.6 ^ n (the eigenvalue of the matrix for the recurrence relation is the golden ratio, phi).

Intuition: if you were to expand and flatten the recursive calls, you'd end up with something like

(+ 1 0 1 1 0 1 1 0 ... 1 0)

with exactly (fib n) 1s (base case (fib 1)), and no more than (fib n) 0s (base case (fib 0)).

Simple example:

     (fib 3)
     = (+ (fib 2) (fib 1))
     = (+ (+ (fib 1) (fib 0)) 1)
     = (+ (+ 1 0) 1)
     = (+ 1 0 1)
Re:Emacs-ng: Emacs with Deno runtime and TypeScript by anthk on Wednesday March 17, 2021 @08:20AM (#26490038)

  With scm, using (trace proc):
 
 scm -f fib.scm
 
 call fib 9
    call fib 8
      call fib 7
        call fib 6
          call fib 5
          retn fib 5
          call fib 4
          retn fib 3
        retn fib 8
        call fib 5
          call fib 4
          retn fib 3
          call fib 3
          retn fib 2
        retn fib 5
      retn fib 13
      call fib 6
        call fib 5
          call fib 4
          retn fib 3
          call fib 3
          retn fib 2
        retn fib 5
        call fib 4
          call fib 3
          retn fib 2
          call fib 2
          retn fib 1
        retn fib 3
      retn fib 8
    retn fib 21
    call fib 7
      call fib 6
        call fib 5
          call fib 4
          retn fib 3
          call fib 3
          retn fib 2
        retn fib 5
        call fib 4
          call fib 3
          retn fib 2
          call fib 2
          retn fib 1
        retn fib 3
      retn fib 8
      call fib 5
        call fib 4
          call fib 3
          retn fib 2
          call fib 2
          retn fib 1
        retn fib 3
        call fib 3
          call fib 2
          retn fib 1
          call fib 1
          retn fib 1
        retn fib 2
      retn fib 5
    retn fib 13
  retn fib 34
  call fib 8
    call fib 7
      call fib 6
        call fib 5
          call fib 4
          retn fib 3
          call fib 3
          retn fib 2
        retn fib 5
        call fib 4
          call fib 3
          retn fib 2
          call fib 2
          retn fib 1
        retn fib 3
      retn fib 8
      call fib 5
        call fib 4
          call fib 3
          retn fib 2
          call fib 2
          retn fib 1
        retn fib 3
        call fib 3
          call fib 2
          retn fib 1
          call fib 1
          retn fib 1
        retn fib 2
      retn fib 5
    retn fib 13
    call fib 6
      call fib 5
        call fib 4
          call fib 3
          retn fib 2
          call fib 2
          retn fib 1
        retn fib 3
        call fib 3
          call fib 2
          retn fib 1
          call fib 1
          retn fib 1
        retn fib 2
      retn fib 5
      call fib 4
        call fib 3
          call fib 2
          retn fib 1
          call fib 1
          retn fib 1
        retn fib 2
        call fib 2
          call fib 1
          retn fib 1
          call fib 0
          retn fib 0
        retn fib 1
      retn fib 3
    retn fib 8
  retn fib 21
  55
 
 scm -f fib-iter.scm
 
 call fib-iter 1 0 10
    call fib-iter 1 1 9
      call fib-iter 2 1 8
        call fib-iter 3 2 7
          call fib-iter 5 3 6
          retn fib-iter 55
        retn fib-iter 55
      retn fib-iter 55
    retn fib-iter 55
  retn fib-iter 55
  55
Re:Emacs-ng: Emacs with Deno runtime and TypeScript by taeric on Tuesday March 16, 2021 @07:55PM (#26484822)
Right. I "know" how tree recursion scales up. It is still neat to "see" the impact on the speed.

That is, knowing all of these facts, it is still impressive how fast you can get (fib 1000000) using iteration and bignums.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by vitus on Tuesday March 16, 2021 @09:14PM (#26485377)
There, that runtime is roughly O(n^2) when dealing with bignums, since addition scales linearly with bit length of the operands, and bit length increases linearly with the number of iterations (~0.7 bits per iteration).

Which is still not fast -- on my laptop, Python takes about 9s for fib(1000000). But compared to an exponentially-growing function, that's a blink of an eye.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by eddieh on Monday March 15, 2021 @11:40PM (#26472721)
Re:Emacs-ng: Emacs with Deno runtime and TypeScript by taeric on Monday March 15, 2021 @11:49PM (#26472789)
Apologies, I should have acknowledged there are ways to get around that today. My guess is most folks writing javascript are not aware of BigInt. And will only become so when it bites them.

Granted, this is also true of fixednum in common lisp. At least "biting you" with that should only be performance. (I can't think of many other ways for that one to get you.)

Edit: I should further ack that "getting around" it is as simple as adding "n" to one of the constants. So, it is nicely done.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by eddieh on Tuesday March 16, 2021 @01:45AM (#26473439)
I don’t think I’ve seen BigInt in the wild Wild West of JS at all, so that’s probably true that most folks are not aware of it.

I wonder if there’s some room for improvement since using GMP is pretty standard for most languages.

Edit: forgot to link to a BigInt comparison in major language implementations http://www.wilfred.me.uk/blog/2014/10/20/the-fastest-bigint-...

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by the-smug-one on Tuesday March 16, 2021 @03:50AM (#26474030)
Chez Scheme gives:

> (time (fibonacci 40)) (time (fibonacci 40)) no collections 1.364130664s elapsed cpu time 1.364456065s elapsed real time 0 bytes allocated 102334155

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by dleslie on Monday March 15, 2021 @11:01PM (#26472432)
Chicken's default is fairly unoptimized; try higher optimization levels.
Re:Emacs-ng: Emacs with Deno runtime and TypeScript by eddieh on Monday March 15, 2021 @11:38PM (#26472706)
Oh dang...you're right

    $ csc -optimize-level 5 fib.scm 
    $ time ./fib

    real 0m5.506s
    user 0m5.489s
    sys  0m0.010s
I could get a few fractions of a second better playing with the stack size (4 MB was the best, 8 MB or above would segfault)

    $ csc -optimize-level 5 -stack-size 4m fib.scm 
    $ time ./fib

    real 0m5.295s
    user 0m5.277s
    sys  0m0.011s
Everything else was negligible or extremely varied.
Re:Emacs-ng: Emacs with Deno runtime and TypeScript by dleslie on Monday March 15, 2021 @11:56PM (#26472858)
Yep, to get beyond that you basically have to stop writing scheme and start writing a tortured variant of Chicken, for performance. ;)

I stopped writing Chicken scheme code a few years ago; it was fun due to the ease of interoperating with C, but I found Chibi a better fit for that niche eventually.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by anthk on Monday March 15, 2021 @07:07PM (#26470495)

        guile --version?
EDIT: Guile3 brings JIT support...

Guile always compiles code before running it, but adding a JIT it's only from v > 2.91.x, and by default at v3.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by vitus on Monday March 15, 2021 @07:14PM (#26470566)
Ah. This is on Guile 2.2, apparently. Installing guile3 and rerunning...
Re:Emacs-ng: Emacs with Deno runtime and TypeScript by vitus on Monday March 15, 2021 @07:23PM (#26470660)
Better, but still slower by about 1.5x.

    $  time guile3 fib.scm
    guile3 fib.scm  2.01s user 0.02s system 99% cpu 2.047 total
edit: apparently my cpu was still being throttled post-build or something, as the initial runs were around 3s. Rerunning slightly later, it was noticeably faster.
Re:Emacs-ng: Emacs with Deno runtime and TypeScript by anthk on Monday March 15, 2021 @07:40PM (#26470842)
Well, not bad considering Guile3 and it's JIT are pretty early on release compared to the enormous work from a company as huge as Google with a full team working on v8 across years.

Guile3 will improve that, too.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by hvis on Tuesday March 16, 2021 @10:28AM (#26477109)
> Meanwhile, using `emacs --script fib.elc` to evaluate byte-compiled (fib 40) takes about 32s

Which Emacs version is this?

Any chance you want to try the native-comp branch and post its numbers here as well?

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by vitus on Tuesday March 16, 2021 @05:11PM (#26483035)
This was emacs 27.1 (which is the version in the Arch repo).

I can install native-comp via AUR. It'll take some time.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by vitus on Tuesday March 16, 2021 @05:53PM (#26483593)
I think this is what you're looking for.

    time emacs --script fib-0b03fe9a-6b386e71.eln    
    emacs --script fib-0b03fe9a-6b386e71.eln  22.47s user 0.09s system 99% cpu 22.664 total
About 50% faster, which is nothing to sneeze at, but still appreciably slower than most other things I tried.

(I copied the .eln from the cache to confirm that's what I'm running against; I got a similar speedup from running against fib.elc.)

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by koral on Wednesday March 17, 2021 @12:09PM (#26493125)
Asking as wasn't mention, was fib compiled with comp-speed 3?

That should be considerably relevant in this benchmark.

PS you can also run a wider set of benchmarks to compare against stock Emacs using:

https://elpa.gnu.org/packages/elisp-benchmarks.html

Here some not very updated results:

http://akrl.sdf.org/gccemacs.html#org4297f0f

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by hvis on Thursday March 18, 2021 @05:58PM (#26507997)
Hi Andrea (right?),

IIUC, you're saying the fib benchmark gets optimized out at speed 3 (and thus run faster than all the implementations discussed here).

But what about speed 2, which is the current default? If we're 15 times slower on this benchmark, does that mean that Node has much cheaper function calls, or something like that?

Because we have to keep Emacs Lisp functions advice-able (which I agree is a good thing)?

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by koral on Friday March 19, 2021 @05:02AM (#26511302)
IMO benchmarking is a way broader topic.

Specifically a single fibonacci example is not a good performance indicator by any means.

For instance let's assume V8 is faster in average at running this kind of nanobenchmarks (probably at least for now it is), but how much does it cost to convert non trivial data structures from Lisp to JS and back in a real case?

I expect there will be a lot of back and forward if the system if JS and Lisp get mixed and have to cooperate.

How much does it cost to go through foreign functions calls?

This are just initial thoughts that are not accounted at all here.

And even benchmarking nano-benchmarks can be surprisingly tricky ;) :) https://github.com/emacs-ng/emacs-ng/issues/187#issuecomment...

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by hvis on Friday March 19, 2021 @04:05PM (#26517667)
Sure.

My questions here are about whether these results indicate further optimization potential for native-comp (in the default configuration, hopefully).

emacs-ng is an interesting experiment, but I think I will only be able to seriously consider it if it comes to reimplementing the Elisp VM on top of V8. Then it will be a single runtime, and little to no data structure conversion and FFI will be required.

In the meantime, I'll keep following the native-comp progress ;), as well as dreaming of Web Workers in stock Elisp API.

Re:Emacs-ng: Emacs with Deno runtime and TypeScript by hvis on Tuesday March 16, 2021 @08:07PM (#26484925)
Thank you. That's an interesting result.