Follow

test.rb:

puts "hello world\n"

0.04s real, 1,403 syscalls, 12.83 MiB of disk space required

test.py:

print("hello world")

0.02s real, 1,202 syscalls, 151 MiB of disk space required

test.c (glibc):

int puts(const char *s);

int main(int argc, char *argv[]) {
puts("hello world");
}

0s real, 67 syscalls, 46 MiB of disk space required (glibc cannot be statically linked) + 14 KiB for stripped binary

test.c (musl libc):

int puts(const char *s);

int main(int argc, char *argv[]) {
puts("hello world");
}

0s real, 7 syscalls, 14 KiB of disk space required

test.S (linux):

section .text
global _start
_start:
mov rdx, len
mov rsi, msg
mov rdi, 1
mov rax, 1
syscall

mov rdi, 0
mov rax, 60
syscall

section .rodata
msg: db "hello world", 10
len: equ $-msg

0s real, 2 syscalls, 8.5 KiB of disk space required

Size of the instructions + data without the ELF wrapper: 52 bytes

@schlink

test.rs

fn main() {
println!("hello world");
}

0s, 125 syscalls, 194 KiB

@sir how good does lua do? The arch linux packages of both lua and luajit are only about 1MB. (gcc-libs of lua is large though, whereas luajit only needs readline.. oh needs some more behind that too)

@jasper @sir

test.lua (linux, Lua 5.3.3)

print("hello world")

0.002s real, 75 syscalls, no clue how large the Lua runtime is these days

@jasper @sir And before someone asks, 13 unique syscalls.

@jasper @sir Would also be interested in lua results! Especially since it's said to be fast and lightweight :)

@phel @jasper I decided to omit lua because it's not really used in the same way as any of the other languages here. It's meant to be embedded into other things

@sir Maybe originally, but people write complete things in lua these days, games, XMPP servers and stuff, and they're not doing it out of spite or ironically.

@sir @phel well @Vexatos gives a fairly low (75) number of syscalls for an interpreted language.(he doesn't say if it's lua/luajit)

I presume you're interested in finding cases where these numbers are good...

@steph aye, which actually gets one too many syscalls but w/e

@sir

test.cr (musl libc)

puts "Hello World"

0s real, 183 syscalls, 867.2KiB for stripped binary

so, better than go, which is something

@steph crystal version and musl version please. Statically linked?

@sir shit, it wasn't statically linked

with static linking it's 935.2K and 144 syscalls
@sir this is alpine latest with crystal 0.32.1 and musl 1.1.24

@espectalll @steph @sir

test.jl (linux, julia 1.3.0)

println("hello world")

0.44s real, 2080 syscalls, 360MB is the current unpacked size of julia

If we measure using the time macro (i.e. speed and resources at runtime) it is
0.002s real, 1.97KiB used

I hope I did this right. Can you tell it's not made for this?

@Vexatos @espectalll @steph how many unique syscalls? You can find out by trimming the first and last line out of the strace log and running this command:

cut -d'(' -f1 < trace | sort -u | wc -l

@Vexatos @espectalll @steph thanks! And can I have that unpacked julia size again, but in KiB?

@sir @espectalll @steph I just reran everything with latest julia (1.3.1).

test.jl (linux, julia 1.3.1)

println("hello world")

0.41s real, 1670 syscalls (42 unique), 344563 KiB

time macro outputs 0.002s, 1.98KiB

@sir @espectalll @steph The absolute number of syscalls seems to slightly fluctuate, but it is much lower with the updated version. The number of unique calls stays the same, as it should.

@sir @espectalll @steph aaaand it turns out I am an idiot, I forgot I had some weird julia config. Here are the numbers on an actually fresh system. Ignore everything above.... Sorry.

test.jl (linux, julia 1.3.1 and without silly configs)

println("hello world")

0.122s real, 913 syscalls (41 unique), 344563 KiB

time macro outputs 0.009s, 1.98KiB

@Vexatos @sir @espectalll going to llvm ir then jitting isn't exactly the most efficient for small programs :P

@steph @sir @espectalll Not to mention the multiple processing steps in Julia itself.

@steph what commands do I use to build this, and the static version?

@sir crystal build test.cr

crystal build --static test.cr

obviously the latter fails on glibc because glibc is a trashfire

@steph save me a little bit of effort, how many unique syscalls for both versions?

@sir

non-static musl (26 syscalls)

1 arch_prctl
1 clock_gettime
1 execve
1 exit_group
1 getcwd
1 membarrier
1 pipe
1 set_tid_address
1 sigaltstack
1 write
2 brk
2 getrandom
2 ioctl
2 madvise
3 clone
3 fstat
4 close
4 read
8 futex
10 mprotect
10 rt_sigaction
11 fcntl
11 open
13 rt_sigprocmask
22 mmap
64 mremap

static musl (24 syscalls)

1 arch_prctl
1 clock_gettime
1 close
1 execve
1 exit_group
1 getcwd
1 open
1 pipe
1 read
1 set_tid_address
1 sigaltstack
1 write
2 getrandom
2 ioctl
2 madvise
3 brk
3 clone
5 mprotect
8 fcntl
8 futex
10 mmap
10 rt_sigaction
13 rt_sigprocmask
64 mremap

@steph what is the size of the dynamic binary including any files required at runtime (libc, loader, etc)?

@sir

868.0K ./test
580.0K /lib/ld-musl-x86_64.so.1
4.0K /usr/lib/libpcre.so.1
4.0K /usr/lib/libevent-2.1.so.7
76.0K /usr/lib/libgcc_s.so.1
580.0K /lib/ld-musl-x86_64.so.1

2.1MiB
@sir the breakout figures aren't correct cause libpcre and libevent are symlinks

the total is correct
@sir crystal is in alpine repos, it's not that hard to reproduce

@sir so, basically, you're measuring the overhead of startup+teardown+issuing a single console print statement across a variety of languages?

@jeff not finished calculating disk usage for Java, but it's 0.07s real / 227 syscalls

@sir dont forget you have to separately uninstall the ask toolbar that comes with the jvm.
Sign in to participate in the conversation
Mastodon

The social network of the future: No ads, no corporate surveillance, ethical design, and decentralization! Own your data with Mastodon!