I am new to Scala so it might show. I am learning it for one of my classes and have to write a performance benchmark. I have written the Sieve of Eratosthenes in both Node.js and Scala, and my Node.js version runs much much quicker for n larger than 100,000. At n = 100,000 the Scala version runs in around a minute where as the Node.js one runs in milliseconds.
As far as I know the Scala version is implemented correctly as it finds the first few primes correctly.
The big disparity in time leads me to believe it's an algorithmic issue and the two pieces of code likely have different time complexities, but looking at the two pieces of code I don't see any stark differences other than iterating the list a couple extra times in the scala version (with the zipIndex and mapping).
Any help would be appreciated.
This is my Scala method
// Sieve of Eratosthenes
// pseudo code from https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
def sieve (n: Integer) = {
// Let A be an array of Boolean values, indexed by integers 2 to n,
// initially all set to true.
var A = new ListBuffer[Boolean]()
var i = 2
for (i <- 2 to n) {
A += true
}
// for i = 2, 3, 4, ..., not exceeding √n:
// if A[i] is true:
// for j = i^2, i^2+i, i^2+2i, i^2+3i, ..., not exceeding n:
// A[j] := false.
i = 2
for ( i <- 2 to Math.sqrt(n.toDouble).toInt ) {
if(A(i - 2)) {
var j = 0
for ( j <- i * i to n by i ) {
A(j - 2) = false
}
}
}
// Output: all i such that A[i] is true.
A.zipWithIndex.filter{case (b, i) => b }.map{ case (b, i) => i + 2 };
}
This is my Node.js code:
let _ = require('lodash');
// Sieve of Eratosthenes
// https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
function int (str, base=10) {
return parseInt(str, base);
}
// Input: an integer n > 1.
let n = int(process.argv[2]);
// Let A be an array of Boolean values, indexed by integers 2 to n,
// initially all set to true.
let A = _.range(n+1)
A[0] = false
A[1] = false
// for i = 2, 3, 4, ..., not exceeding √n:
// if A[i] is true:
// for j = i2, i2+i, i2+2i, i2+3i, ..., not exceeding n:
// A[j] := false.
for(let i = 2; i <= Math.sqrt(n); ++i) {
if(A[i]) {
for(let j = i*i; j <= n; j += i) {
A[j] = false;
}
}
}
let primes = A.filter((el)=>el);