1

So I made a JS file to calculate a list of number below 10 that go through certain properties.

// Config //
const maxNum = 30; //The largest number that can be used (even)
const maxLength = maxNum; // The max length of a group

// Default vars
const res = [];
const even = [];
const odd = [];
for(let i = 1; i < maxNum + 1; i++) 
    i%2==0 ? even.push(i) : odd.push(i);

const addNumber = (curr, max, e) => {
    if(curr.length == max) return res.push(curr);
    for(let num of e ? even : odd) {
        if(curr.includes(num) || curr[curr.length-1] > num) continue;
        addNumber([...curr, num], max, !e);
    }
}

for(let i = 1; i < maxLength + 1; i++)
    addNumber([], i, false);

Then I had saw Julia as a good and 'performing' language for Math, so decided to re-write it there. However after doing a benchmark (using Hyperfine) I got an unexpected result: (Julia: 368ms to 395, Bun [with node just behind it]: 13ms to 125ms)

enter image description here

So I did run some warmed up test, same history, and even increasing the maxNum up to 30 (Get really low behind that). And once more bun and node destroyed Julia. So I just wanted to know if it was my code the issue:

const MaxNumber = 10; # Needs to be even!

const res = Vector{Int16}[];
const even = [n*2 for n in 1:(convert(Int16, MaxNumber/2))];
const odd = [n*2-1 for n in 1:(convert(Int16, MaxNumber/2))];

function addNumber(curr::Vector{Int16}, max::Number, toDoEven::Bool)
    if (length(curr) === max)
        return push!(res, curr);
    end
    for num::Int16 in (toDoEven ? even : odd)
        if(!isempty(curr) && (num in curr || last(curr) > num))
            continue;
        end
        addNumber(vcat(curr, num), max, !toDoEven);
    end
end

for i in 1:MaxNumber
    addNumber(Int16[], i, false)
end

(The test were done with the Int8 instead of Int16, changed it to support the 30 MaxNumber length)

So, is it un-optimized code or something I am doing wrong, or is node and bun (while being compiled) defeating Julia (JIT)

BelMat
  • 93
  • 8
  • 11
    Pretty sure this is just that you're measuring julia startup time (and compilation time). – Oscar Smith Sep 09 '22 at 02:15
  • 1
    In which way? `julia test.jl` isn't the right way? (Normally running a file) – BelMat Sep 09 '22 at 02:32
  • 1
    As Oscar has mentioned, hyperfine is almost certainly measuring julia startup and compilation on every iteration, whereas for bun that only appears to happen on the first iteration (see the warning in the output you put in the question for evidence of this). Also it's worth having a look at the [Performance Tips](https://docs.julialang.org/en/v1/manual/performance-tips/) section of the julia manual as you're breaking the first two rules. – Colin T Bowers Sep 09 '22 at 03:16
  • 5
    To expand on this, if you want an accurate reading of how fast your `addNumber` function is in julia, try using the `BenchmarkTools.jl` package within a single session of julia on your function. But please check the performance tips first and adjust your function accordingly. As a general comment on using Julia, I would try to avoid using globals entirely in pretty much everything I write. – Colin T Bowers Sep 09 '22 at 03:18
  • 2
    Julia version runs in 56 μs on my machine, that's 6.6k times faster than what you report. I'm curious how you benchmarked this? I'm not familiar with hyperfine. – AboAmmar Sep 09 '22 at 11:45
  • Yeah so to benchmark this I used hyperfine that just repeats the run. After testing some of the improvements I got no benefit and even less performance... Found nothing in the frist two rules that benefited me: 1. Performance critical code should be inside a function - I have little to no code outside a funcion, and it's just calling another function, so no perpouse on fixing that. 2. Avoid untyped global variables, slower. `@time` gives ` 0.000861 seconds (4.85 k allocations: 180.547 KiB)` which, correct me if I am wrong, is a benefit, however I do want it to include Julia's startup time – BelMat Sep 10 '22 at 03:52
  • If you need to include startup time, something like PackageCompiler would be a better option here (e.g. [Speeding up Julia on terminal](https://stackoverflow.com/questions/66159138/speeding-up-julia-on-terminal-for-the-second-run/66160011#66160011)). Doing `julia test.jl` does work, but comparing that to node is like comparing `gcc test.c; ./test` to node. – Alexander L. Hayes Sep 15 '22 at 03:36

0 Answers0