nodejs / help

:sparkles: Need help with Node.js? File an Issue here. :rocket:
1.46k stars 279 forks source link

Arm performance issue #4151

Closed solaris111 closed 3 months ago

solaris111 commented 1 year ago

Details

I encountered some performance slowdowns in Node.js 18.16 while developing for IOT devices.

To reproduce the problem, I wrote a simple prime number generation program:
C version, compiled with gcc -o prime prime1.c -O2 -lm (all test platforms were 64-bit)

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>

int main() {
  const long long Prime = 10000000;
  long long sqrt_i, i, n, j;
  float delta_sec;
  struct timeval in_time, out_time;
  n = 0;
  gettimeofday(&in_time, NULL);
  for (i = 3; i <= Prime; i = i + 2) {
    sqrt_i = sqrt(i);
    for (j = 2; j <= sqrt_i; j++)
      if (i % j == 0) break;
    if (j > sqrt_i) {
      n++;
    }
  }
  gettimeofday(&out_time, NULL);
  delta_sec = (out_time.tv_sec - in_time.tv_sec) +
              (out_time.tv_usec - in_time.tv_usec) * 1e-6;
  printf("prime count: %lld   delta sec: %.3f Sec\n", n, delta_sec);
  printf("size of short:%d\n", sizeof(short));
  printf("size of int:%d\n", sizeof(int));
  printf("size of long:%d\n", sizeof(long));
  printf("size of long long:%d\n", sizeof(long long));
  printf("size of float:%d\n", sizeof(float));
  printf("size of double:%d\n", sizeof(double));
}

JS version

const Prime = 10000000;
let sqrt_i;
let in_time, out_time;
let n = 0;
let i, j;
in_time = new Date().getTime();
nextPrime: for (i = 3; i <= Prime; i = i + 2) {
  sqrt_i = Math.sqrt(i);
  for (j = 2; j <= sqrt_i; j++) {
    if (i % j == 0) break;
  }
  if (j > sqrt_i) n++;
}
out_time = new Date().getTime();
console.log(`Total time: ${(out_time - in_time) / 1000}S Total Prime: ${n}`);

JS version is almost as fast as C counterpart on Raspberry Pi 4B (overclocked, 2.0GHz)

pi@Pi-4B:~/devel/nodejs $ node --jitless prime.js
Warning: disabling flag --expose_wasm due to conflicting flags
Total time: 118.194S Total Prime: 664578

pi@Pi-4B:~/devel/nodejs $ node prime.js
Total time: 7.846S Total Prime: 664578

pi@Pi-4B:~/devel/nodejs $ ./prime
prime count: 664578   delta sec: 7.840 Sec

Running the same programs on Intel N4200, A72, and A76 CPUs yielded similar results.

However, JS version took nearly twice as much time as C version to execute on Raspberry Pi 3B+:

pi@Pi-3plus:~/devel/nodejs $ node --jitless prime.js
Warning: disabling flag --expose_wasm due to conflicting flags
Total time: 462.267S Total Prime: 664578

pi@Pi-3plus:~/devel/nodejs $ node prime.js
Total time: 29.455S Total Prime: 664578

pi@Pi-3plus:~/devel/nodejs $ ./prime
prime count: 664578   delta sec: 14.381 Sec

Same occurence was found on Rk3399 (2 A73 and 4 A53 cores, 4GB RAM):

pi@R4S:~/devel/nodejs$ taskset -c 5 node prime.js
Total time: 7.875S Total Prime: 664578
pi@R4S:~/devel/nodejs$ taskset -c 5 ./prime
prime count: 664578   delta sec: 7.717 Sec
pi@R4S:~/devel/nodejs$ taskset -c 0 node prime.js
Total time: 25.485S Total Prime: 664578
pi@R4S:~/devel/nodejs$ taskset -c 0 ./prime
prime count: 664578   delta sec: 12.402 Sec

as well as Rk3588S (4 A75 and 4 A55 cores, 16GB RAM):

firefly@firefly:~/nodejs$ taskset -c 6 ./prime
prime count: 664578   delta sec: 6.899 Sec
firefly@firefly:~/nodejs$ taskset -c 6 node prime.js
Total time: 6.868S Total Prime: 664578
firefly@firefly:~/nodejs$ taskset -c 2 ./prime
prime count: 664578   delta sec: 11.010 Sec
firefly@firefly:~/nodejs$ taskset -c 2 node prime.js
Total time: 22.605S Total Prime: 664578

and also on RK3308 (rockpi-s):

i@Pi-S:~/nodejs$ node prime.js
Total time: 36.975S Total Prime: 664578
pi@Pi-S:~/nodejs$ ./prime
prime count: 664578   delta sec: 16.707 Sec

I would like to know what caused this slowdown as well as how to optimize performance for A53 CPUs. Many thanks!

Node.js version

pi@R4S:~/devel/nodejs$ node -v
v18.16.0
pi@R4S:~/devel/nodejs$ apt show nodejs
Package: nodejs
Version: 18.16.0-deb-1nodesource1
Priority: optional
Section: web
Maintainer: Operations Nodesource <operations@nodesource.com>
Installed-Size: 186 MB
Provides: nodejs-dev, nodejs-doc, nodejs-legacy, npm
Depends: libc6 (>= 2.28), libgcc1 (>= 1:4.2), libstdc++6 (>= 5.2), python3-minimal, ca-certificates
Conflicts: nodejs-dev, nodejs-doc, nodejs-legacy, npm
Replaces: nodejs-dev (<= 0.8.22), nodejs-legacy, npm (<= 1.2.14)
Homepage: https://nodejs.org
Download-Size: 28.0 MB
APT-Manual-Installed: yes
APT-Sources: https://deb.nodesource.com/node_18.x focal/main arm64 Packages

Example code

No response

Operating system

pi@R4S:~/devel/nodejs$ uname -a
Linux R4S 5.15.11 #4 SMP PREEMPT Thu Jan 20 15:59:05 CST 2022 aarch64 aarch64 aarch64 GNU/Linux

pi@Pi-3plus:~ $ uname -a
Linux Pi-3plus 6.1.21-v8+ #1642 SMP PREEMPT Mon Apr  3 17:24:16 BST 2023 aarch64 GNU/Linux

Scope

Performance on Arm A53, A55, and A35 CPUs

Module and version

Not applicable.

preveen-stack commented 1 year ago

Can you convert the script into an executable with https://github.com/vercel/pkg and see how the timing looks like

solaris111 commented 1 year ago

I will try it later.

preveen-stack commented 1 year ago

Anybody has access to raspberry pi 3 please try to reproduce this issue

github-actions[bot] commented 4 months ago

It seems there has been no activity on this issue for a while, and it is being closed in 30 days. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.

github-actions[bot] commented 3 months ago

It seems there has been no activity on this issue for a while, and it is being closed. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.