Java vs NodeJS
How can node.js be faster than c and java? Benchmark comparing node.js, c, java and python - Stack Overflow
Is Node.js Really Faster Than Java?
Java/ Spring Boot or NodeJS/ Typescript? Why?
Videos
I am watching the progress made towards faster runtime in node.js, and it feels that the performance advantage of java is almost gone for the average app. I am trying to think about reasons why one would now choose java over node in a new project, and i can't think of any. I would like to hear some opinions
Hello everyone!
What Are The advantage and disadvantages of using Java(springboot) instead of NodeJS as the back end of my web application.
Thanks in advance.
I spent a couple of days investigating the performance difference between JS/V8 and C, focusing first of all on the Hydrogen IR generated by the V8 engine. However, after making sure that no extraordinary optimizations are present there, I got back to the analysis of the assembly output and it struck me that the answer was a very simple one, boiling down to the couple of sentences in Jay Conrod's blog post on internals of V8:
According to the spec, all numbers in JavaScript are 64-bit floating point doubles. We frequently work with integers though, so V8 represents numbers with 31-bit signed integers whenever possible.
The example at hand allows fitting all computations in 32 bits and node.js takes full advantage of that! The C code utilizes the long type, which on OP's (as well as my) platform happens to be a 64-bit type. Thus, it is a 32-bit arithmetic vs 64-bit arithmetic issue, mostly due to the expensive division/remainder operation.
If long in the C code is replaced with int, then the binary produced by gcc beats node.js.
Also, if the loop is made to look for primes over a range that is outside the realm of 32-bit numbers the performance of the node.js version drops significantly.
Proof
The used source code is found further in the answer, below the results.
Counting primes less than 10 million with C and node.js
$ gcc count_primes.c -std=c99 -O3 -lm -o count_primes_long
$ sed 's/long/int/g; s/%li/%i/g' count_primes.c > count_primes_int.c
$ gcc count_primes_int.c -std=c99 -O3 -lm -o count_primes_int
# Count primes <10M using C code with (64-bit) long type
$ time ./count_primes_long 0 10000000
The range [0, 10000000) contains 664579 primes
real 0m4.394s
user 0m4.392s
sys 0m0.000s
# Count primes <10M using C code with (32-bit) int type
$ time ./count_primes_int 0 10000000
The range [0, 10000000) contains 664579 primes
real 0m1.386s
user 0m1.384s
sys 0m0.000s
# Count primes <10M using node.js/V8 which transparently does the
# job utilizing 32-bit types
$ time nodejs ./count_primes.js 0 10000000
The range [ 0 , 10000000 ) contains 664579 primes
real 0m1.828s
user 0m1.820s
sys 0m0.004s
Performance figures in the vicinity of the limit of signed 32-bit integers
Counting the primes in the range of length 100,000 starting at the number contained in the first column:
| node.js | C (long)
-----------------------------------
2,000,000,000 | 0.293s | 0.639s # fully within the 32-bit range
-----------------------------------
2,147,383,647 | 0.296s | 0.655s # fully within the 32-bit range
-----------------------------------
2,147,453,647 | 2.498s | 0.646s # 50% within the 32-bit range
-----------------------------------
2,147,483,647 | 4.717s | 0.652s # fully outside the 32-bit range
-----------------------------------
3,000,000,000 | 5.449s | 0.755s # fully outside the 32-bit range
-----------------------------------
count_primes.js
"use strict";
var isPrime = function(n){
if (n < 2) {return false};
if (n === 2) {return true};
if (n === 3) {return true};
if (n % 2 === 0) {return false};
if (n % 3 === 0) {return false};
var sqrtOfN = Math.sqrt(n);
for (var i = 5; i <= sqrtOfN; i += 6){
if (n % i === 0) {return false}
if (n % (i + 2) === 0) {return false}
}
return true;
};
var countPrime = function(S, E){
var count = 0;
for (let i = S; i < E;i++){
if ( isPrime(i) ) { ++count; }
}
return count;
};
if( process.argv.length != 4) {
console.log('Usage: nodejs count_prime.js <range_start> <range_length>');
process.exit();
}
var S = parseInt(process.argv[2]);
var N = parseInt(process.argv[3]);
var E = S+N;
var P = countPrime(S, E);
console.log('The range [', S, ',', E, ') contains', P, 'primes');
count_primes.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define true 1
#define false 0
int isPrime (register long n){
if (n < 2) return false;
if (n == 2) return true;
if (n == 3) return true;
if (n % 2 == 0) return false;
if (n % 3 == 0) return false;
double sqrtOfN = sqrt(n);
for (long i = 5; i <= sqrtOfN; i += 6){
if (n % i == 0) return false;
if (n % (i + 2) == 0) return false;
}
return true;
};
int main(int argc, const char * argv[]) {
if ( argc != 3 ) {
fprintf(stderr, "Usage: count_primes <range_start> <range_length>\n");
exit(1);
}
const long S = atol(argv[1]);
const long N = atol(argv[2]);
register long count = 0;
for (register long i = S; i < S + N; i++){
if ( isPrime(i) ) ++count;
}
printf("The range [%li, %li) contains %li primes\n", S, S+N, count);
}
When I ran your code in python with a new algorithm:
real 0m3.583s
user 0m3.297s
sys 0m0.094s
Faster than the C benchmark you have above. I think that a simpler language helps you design better algorithms, but that is my opinion. (Also can use multiprocessing to make even faster)
def allPrimes(N):
is_prime = [1]*N
# We know 0 and 1 are composites
is_prime[0] = 0
is_prime[1] = 0
i = 2
# This will loop from 2 to int(sqrt(x))
while i*i <= N:
# If we already crossed out this number, then continue
if is_prime[i] == 0:
i += 1
continue
j = 2*i
while j < N:
# Cross out this as it is composite
is_prime[j] = 0
# j is incremented by i, because we want to cover all multiples of i
j += i
i += 1
return is_prime
print("total", sum(allPrimes(10000000)))
Issac claims Node.js is faster than Java because it uses on non-blocking calls (not just non-blocking I/O) while Java web apps usually rely on multi-threading.
http://strongloop.com/strongblog/node-js-is-faster-than-java/