V: Make v even faster with release/optimization flags

Created on 9 Apr 2020  Â·  16Comments  Â·  Source: vlang/v

This is a fib calculation code copied from https://github.com/drujensen/fib repo.

fn fib(n i64) i64 {
    if n <= 1 {
        return 1
    }
    return fib(n - 1) + fib(n - 2)
}

fn main() {
    println(fib(46))
}

Results:

➜  v --version
V 0.1.24 0d93eeb

➜  time v fib.v 
v fib.v  0.21s user 0.02s system 99% cpu 0.221 total

➜  time ./fib
2971215073
./fib  9.22s user 0.00s system 99% cpu 9.219 total

The nim, rust, c etc runs around 4s in my pc.
v takes around 9s.
It builds fast, but falls behind on release/optimization flags.

For example, A look at rust with some optimization flags. It build faster and ran faster.

➜  time rustc -C opt-level=s fib.rs
rustc -C opt-level=s fib.rs  0.12s user 0.02s system 97% cpu 0.140 total
➜  time ./fib 
2971215073
./fib  4.99s user 0.00s system 99% cpu 4.997 total

Now let's see the c,

➜  gcc -o fib fib.c
➜  time ./fib
2971215073 
./fib  9.26s user 0.00s system 99% cpu 9.258 total

The v and c had almost same results. However C supports optimization flags.

➜  gcc -Ofast -o fib fib.c
➜  time ./fib
2971215073 
./fib  4.11s user 0.00s system 99% cpu 4.112 total

Which means v is falling behind without the flags.
If there are indeed some flags, it should be documented.

Though it's mentioned in the homepage,
"In the future V will have its own optimizer."

Is there an ETA for this?

Feature Request

Most helpful comment

No, just profiled it.

@entrptaher if u64 is used, like in C, then the performance is the same.

Would be great if you could submit a PR there.

All 16 comments

v -prod fib.v
6.25s on my PC. but seems that my PC is little bit slower than yours.

Many thanks for showing.

I don't know if I missed anything. It did increase the speed, but not close to the c/rust build. Since it was mentioned "As fast as C".

➜  v --prod fib.v
➜  time ./fib
2971215073
./fib  9.13s user 0.00s system 99% cpu 9.135 total

➜  v -prod fib.v 
➜  time ./fib   
2971215073
./fib  5.08s user 0.00s system 99% cpu 5.081 total

Moreover, if you didn't mention, I wouldn't even known about this flag since it was hidden away :D . Then I searched for it and saw it was mentioned few times in whole codebase, and only once in the https://github.com/vlang/v/blob/2006995020181425a8b3476dd01b16059a7ab419/doc/docs.md#L157 file.

I think we still need different optimization flags and document them.

btw 4s and 5s doesn't seem much, bit it will be a lot when we put a even bigger number, or start doing heavier calculations, for example going through a 1GB json data with lots of loops.

Here is a benchmark using hyperfine for future discussion,

➜  cd v
➜  alias v=~/Downloads/v_linux/v 
➜  v -prod fib.v
➜  hyperfine "./fib"
Benchmark #1: ./fib
  Time (mean ± σ):      5.105 s ±  0.023 s    [User: 5.103 s, System: 0.002 s]
  Range (min … max):    5.087 s …  5.158 s    10 runs

➜  cd c
➜  gcc -Ofast -o fib fib.c
➜  hyperfine "./fib"
Benchmark #1: ./fib
  Time (mean ± σ):      4.148 s ±  0.026 s    [User: 4.146 s, System: 0.001 s]
  Range (min … max):    4.107 s …  4.194 s    10 runs

The compiler is not even finished... we need a lot of improvements.

Yes i think there is a lot of initialization work. I think if we could decrease the initialization we could save some time.

It's documented under v help build, will copy it to v help as well.

The speed should be the same as with C, I'm also getting a 1s difference. Will investigate, pretty sure that's something easy to fix.

A hello world in V is 8339 lines of code in V.

Only because all the builtin modules are re-compiled for each program. This will be fixed with module caching by tomorrow.

Shouldn't impact performance.

Could it be, that the _vinit method takes some time?

No, just profiled it.

@entrptaher if u64 is used, like in C, then the performance is the same.

Would be great if you could submit a PR there.

It's still missing by around 100~250ms though. But I tested it with u64 and results have improved.

Benchmark #1: ./fib
  Time (mean ± σ):      4.345 s ±  0.018 s    [User: 4.342 s, System: 0.001 s]
  Range (min … max):    4.310 s …  4.364 s    10 runs

i made a PR there

Hmm, v has a 200ms overhead for this program for some reason. I guess it's understandable though.

➜  v -cflags "-Ofast" fib.v
➜  time ./fib
2971215073
./fib  4.35s user 0.00s system 99% cpu 4.355 total

It should be literally the same, it compiles to the same code.

You are using time and benchmark. Use benchmark for both programs.

The only overhead V has is some consts initialization, which should be less than 1 ms.

In that case, I am not sure what I'm doing wrong here to get such difference. The reason 46 is choosen is because that is the minimum fib number that produces such huge result 2971215073.

V

I just changed it to u64, and tried using both -prod and -cflags as you can see.

fn fib(n u64) u64 {
    if n <= 1 {
        return 1
    }
    return fib(n - 1) + fib(n - 2)
}

fn main() {
    println(fib(46))
}
➜  v --version
V 0.1.24 0d93eeb
➜  v -cflags "-Ofast" fib.v
➜  hyperfine "./fib"
Benchmark #1: ./fib
  Time (mean ± σ):      4.377 s ±  0.008 s    [User: 4.376 s, System: 0.000 s]
  Range (min … max):    4.367 s …  4.390 s    10 runs

➜  v -prod fib.v           
➜  hyperfine "./fib"
Benchmark #1: ./fib
  Time (mean ± σ):      4.323 s ±  0.012 s    [User: 4.322 s, System: 0.001 s]
  Range (min … max):    4.313 s …  4.353 s    10 runs

C

#include <stdio.h>
#include <stdint.h>

static uint64_t fib(uint64_t n) {
  if (n <= 1) return 1;
  return fib(n - 1) + fib(n - 2);
}

int main(void) {
  printf("%lu \n", fib(46));
  return 0;
}
➜  gcc --version
gcc (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008
➜  gcc -Ofast -o fib fib.c
➜  hyperfine "./fib"
Benchmark #1: ./fib
  Time (mean ± σ):      4.147 s ±  0.024 s    [User: 4.146 s, System: 0.001 s]
  Range (min … max):    4.105 s …  4.178 s    10 runs

v -prod -show_c_cmd fib.v

Here is a result from the command, I ran it twice.

➜  v -prod -show_c_cmd fib.v

==========
cc  -std=gnu11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-unused-result -Wno-unused-function -Wno-missing-braces -Wno-unused-label -O3 -fno-strict-aliasing -flto -Werror=implicit-function-declaration -o "fib" "/home/taher/.cache/v/fib.tmp.c"    -lm -lpthread   -ldl 
cc took 583 ms
=========

➜  v -prod -show_c_cmd fib.v

==========
cc  -std=gnu11 -Wall -Wextra -Wno-unused-variable -Wno-unused-parameter -Wno-unused-result -Wno-unused-function -Wno-missing-braces -Wno-unused-label -O3 -fno-strict-aliasing -flto -Werror=implicit-function-declaration -o "fib" "/home/taher/.cache/v/fib.tmp.c"    -lm -lpthread   -ldl 
cc took 251 ms
=========

I changed my computer to a different one to test if this was only happening on my pc or not. It is indeed missing 200ms.

v

➜  hyperfine --warmup 3 ./fib
Benchmark #1: ./fib
  Time (mean ± σ):      4.791 s ±  0.050 s    [User: 4.791 s, System: 0.000 s]
  Range (min … max):    4.765 s …  4.901 s    10 runs

C

➜  hyperfine --warmup 3 ./fib
Benchmark #1: ./fib
  Time (mean ± σ):      4.577 s ±  0.004 s    [User: 4.576 s, System: 0.001 s]
  Range (min … max):    4.574 s …  4.588 s    10 runs
Was this page helpful?
0 / 5 - 0 ratings

Related issues

taojy123 picture taojy123  Â·  3Comments

medvednikov picture medvednikov  Â·  3Comments

choleraehyq picture choleraehyq  Â·  3Comments

PavelVozenilek picture PavelVozenilek  Â·  3Comments

clpo13 picture clpo13  Â·  3Comments