What's the best profiler for Rust?

#1

Hello,
I’ve been trying to find a good profiler for Rust, but couldn’t find one. I’m a WSL user (so I’m using windows), WITHOUT administrator access. I understand that most debuggers and profilers require admin access (I’ve been fine so far, just print debugging lmao), so if it preferably didn’t need admin access and would run on native windows, great! The next best thing is running on Debian WSL. For the most part, all linux apps work on WSL, AS LONG as they’re not GUI - which rules out things like valgrind (using kcachegrind to visualize and view the result). I’ve tried using perf (installed through sudo apt-get install linux_perf (I forget if there was an underscore or a dash, but it worked)), but when I run perf, I get this:

image

I’m using Debian. Any ideas?

0 Likes

#2

Lmao I asked some other guy this over email, and he trolled me buy responding, “If you can do print debugging, you can do print optimization”. Got a good laugh out of that, but still tho

0 Likes

#3

I had good experiences profiling Rust applications with Visual Studio. Seems like your admin can give you permission to do that as a normal user: https://docs.microsoft.com/en-us/visualstudio/profiling/how-to-set-permissions?view=vs-2017

0 Likes

#4

Nope. I can only communicate with my admin about once a year.

0 Likes

#5

In that case a virtual machine might be your best friend.

0 Likes

#6

Most VMs have some sort of driver, can’t install one

0 Likes

#7

WSL doesn’t need admin privileges, though, and lets you use linux! But disk IO is kind of slow, and there is no GUI support :frowning:

I’ve tried perf on it (debian on WSL), but ran into problems. The screenshot is all the way up.

Or, you know, I could dual boot it in a way that it’s hard to detect the other partition (you can configure it so that a “magic key” opens the OS selector, otherwise it boots into windows). The magic key has to be pressed in a short interval during booting, though.
#tootallynotgivingbadadvicetoothers

1 Like

#8

WSL is not a real full fledged Linux so advanced things like virtualization and instrumentation will not work. Sounds like that laptop is kind of a useless brick in that regard. Sprinkling timers throughout the code it is then :smiley:

2 Likes

#9

Well, gdb worked…

Lmao if I don’t get a profiler working I guess I do just have to do “print optimization” lmao. Sprinkle timers all over the place. Sounds fun. NOT.

0 Likes

#10

Hmm take a look at this, I’m following this as I write this and will see if it works.

0 Likes

#11

Hmm, I’ll try it.

You seem pretty active around here, thanks for all the help in teh past!

1 Like

#12

Doesn’t seem like the link I posted provides too useful data, the names are pretty mangled and doesn’t include actual debugging symbols.

--------------------------------------------------------------------------------
Profile data file 'callgrind.out.1225' (creator: callgrind-3.11.0)
--------------------------------------------------------------------------------
I1 cache:
D1 cache:
LL cache:
Timerange: Basic block 0 - 109840
Trigger: Program termination
Profiled target:  ./main 50000000 (PID 1225, part 1)
Events recorded:  Ir
Events shown:     Ir
Event sort order: Ir
Thresholds:       99
Include dirs:
User annotated:
Auto-annotation:  on

--------------------------------------------------------------------------------
     Ir
--------------------------------------------------------------------------------
527,178  PROGRAM TOTALS

--------------------------------------------------------------------------------
    Ir  file:function
--------------------------------------------------------------------------------
97,643  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-lookup.c:do_lookup_x [/lib/x86_64-linux-gnu/ld-2.23.so]
70,943  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/multiarch/../strcmp.S:strcmp [/lib/x86_64-linux-gnu/ld-2.23.so]
59,498  /build/glibc-Cl5G7W/glibc-2.23/stdio-common/vfscanf.c:_IO_vfscanf [/lib/x86_64-linux-gnu/libc-2.23.so]
56,475  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-addr.c:_dl_addr [/lib/x86_64-linux-gnu/libc-2.23.so]
45,669  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-lookup.c:_dl_lookup_symbol_x [/lib/x86_64-linux-gnu/ld-2.23.so]
30,145  /build/glibc-Cl5G7W/glibc-2.23/elf/../sysdeps/x86_64/dl-machine.h:_dl_relocate_object
28,846  /build/glibc-Cl5G7W/glibc-2.23/stdlib/../stdlib/strtol_l.c:____strtoul_l_internal [/lib/x86_64-linux-gnu/libc-2.23.so]
21,173  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-misc.c:_dl_name_match_p [/lib/x86_64-linux-gnu/ld-2.23.so]
14,367  /build/glibc-Cl5G7W/glibc-2.23/elf/do-rel.h:_dl_relocate_object
11,071  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-lookup.c:check_match [/lib/x86_64-linux-gnu/ld-2.23.so]
 4,821  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/multiarch/../memcpy.S:__GI_memcpy [/lib/x86_64-linux-gnu/libc-2.23.so]
 4,762  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-version.c:_dl_check_map_versions [/lib/x86_64-linux-gnu/ld-2.23.so]
 4,206  /build/glibc-Cl5G7W/glibc-2.23/libio/iogetdelim.c:getdelim [/lib/x86_64-linux-gnu/libc-2.23.so]
 3,544  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-cache.c:_dl_cache_libcmp [/lib/x86_64-linux-gnu/ld-2.23.so]
 3,362  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-deps.c:_dl_map_object_deps [/lib/x86_64-linux-gnu/ld-2.23.so]
 3,264  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/memchr.S:memchr [/lib/x86_64-linux-gnu/libc-2.23.so]
 3,240  /build/glibc-Cl5G7W/glibc-2.23/libio/genops.c:_IO_sputbackc [/lib/x86_64-linux-gnu/libc-2.23.so]
 3,045  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-version.c:match_symbol [/lib/x86_64-linux-gnu/ld-2.23.so]
 2,930  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-load.c:_dl_map_object [/lib/x86_64-linux-gnu/ld-2.23.so]
 2,542  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-load.c:_dl_map_object_from_fd [/lib/x86_64-linux-gnu/ld-2.23.so]
 2,485  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/rawmemchr.S:rawmemchr [/lib/x86_64-linux-gnu/libc-2.23.so]
 1,906  /build/glibc-Cl5G7W/glibc-2.23/elf/get-dynamic-info.h:_dl_map_object_from_fd
 1,890  /build/glibc-Cl5G7W/glibc-2.23/libio/strops.c:_IO_str_init_static_internal [/lib/x86_64-linux-gnu/libc-2.23.so]
 1,782  /build/glibc-Cl5G7W/glibc-2.23/libio/iovsscanf.c:vsscanf [/lib/x86_64-linux-gnu/libc-2.23.so]
 1,725  /build/glibc-Cl5G7W/glibc-2.23/nptl/pthread_getattr_np.c:pthread_getattr_np [/lib/x86_64-linux-gnu/libpthread-2.23.so]
 1,519  /build/glibc-Cl5G7W/glibc-2.23/malloc/malloc.c:_int_malloc [/lib/x86_64-linux-gnu/libc-2.23.so]
 1,460  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-load.c:open_verify.constprop.7 [/lib/x86_64-linux-gnu/ld-2.23.so]
 1,430  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/multiarch/../memset.S:memset [/lib/x86_64-linux-gnu/ld-2.23.so]
 1,408  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-cache.c:_dl_load_cache_lookup [/lib/x86_64-linux-gnu/ld-2.23.so]
 1,374  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-object.c:_dl_new_object [/lib/x86_64-linux-gnu/ld-2.23.so]
 1,248  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-fini.c:_dl_fini [/lib/x86_64-linux-gnu/ld-2.23.so]
 1,221  /build/glibc-Cl5G7W/glibc-2.23/libio/genops.c:_IO_no_init [/lib/x86_64-linux-gnu/libc-2.23.so]
 1,213  /build/glibc-Cl5G7W/glibc-2.23/libio/genops.c:_IO_old_init [/lib/x86_64-linux-gnu/libc-2.23.so]
 1,188  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/multiarch/../memcpy.S:memcpy [/lib/x86_64-linux-gnu/ld-2.23.so]
 1,128  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-minimal.c:__libc_memalign [/lib/x86_64-linux-gnu/ld-2.23.so]
 1,097  /build/glibc-Cl5G7W/glibc-2.23/elf/rtld.c:dl_main [/lib/x86_64-linux-gnu/ld-2.23.so]
 1,036  /build/glibc-Cl5G7W/glibc-2.23/elf/../elf/dl-runtime.c:_dl_fixup [/lib/x86_64-linux-gnu/ld-2.23.so]
 1,019  /build/glibc-Cl5G7W/glibc-2.23/libio/genops.c:_IO_setb [/lib/x86_64-linux-gnu/libc-2.23.so]
   987  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-reloc.c:_dl_relocate_object [/lib/x86_64-linux-gnu/ld-2.23.so]
   972  /build/glibc-Cl5G7W/glibc-2.23/stdio-common/../include/scratch_buffer.h:_IO_vfscanf
   918  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/memcpy.S:mempcpy [/lib/x86_64-linux-gnu/ld-2.23.so]
   918  /build/glibc-Cl5G7W/glibc-2.23/stdio-common/sscanf.c:sscanf [/lib/x86_64-linux-gnu/libc-2.23.so]
   888  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-load.c:open_path [/lib/x86_64-linux-gnu/ld-2.23.so]
   883  /build/glibc-Cl5G7W/glibc-2.23/malloc/malloc.c:_int_free [/lib/x86_64-linux-gnu/libc-2.23.so]
   868  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/strlen.S:strlen [/lib/x86_64-linux-gnu/ld-2.23.so]
   828  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/multiarch/../memcmp.S:bcmp [/lib/x86_64-linux-gnu/ld-2.23.so]
   788  /build/glibc-Cl5G7W/glibc-2.23/malloc/malloc.c:malloc_consolidate [/lib/x86_64-linux-gnu/libc-2.23.so]
   784  /build/glibc-Cl5G7W/glibc-2.23/nptl/cleanup_defer_compat.c:_pthread_cleanup_push_defer [/lib/x86_64-linux-gnu/libpthread-2.23.so]
   656  /build/glibc-Cl5G7W/glibc-2.23/misc/../sysdeps/unix/sysv/linux/wordsize-64/mmap.c:mmap [/lib/x86_64-linux-gnu/libc-2.23.so]
   650  /build/glibc-Cl5G7W/glibc-2.23/elf/../sysdeps/x86_64/dl-trampoline.h:_dl_runtime_resolve_avx [/lib/x86_64-linux-gnu/ld-2.23.so]
   649  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/multiarch/../strchr.S:index [/lib/x86_64-linux-gnu/ld-2.23.so]
   624  /build/glibc-Cl5G7W/glibc-2.23/elf/./dl-map-segments.h:_dl_map_object_from_fd
   600  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-error.c:_dl_catch_error [/lib/x86_64-linux-gnu/ld-2.23.so]
   552  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/cacheinfo.c:intel_check_word [/lib/x86_64-linux-gnu/libc-2.23.so]
   498  /build/glibc-Cl5G7W/glibc-2.23/nptl/../nptl/pthread_mutex_lock.c:pthread_mutex_lock [/lib/x86_64-linux-gnu/libpthread-2.23.so]
   448  /build/glibc-Cl5G7W/glibc-2.23/nptl/cleanup_defer_compat.c:_pthread_cleanup_pop_restore [/lib/x86_64-linux-gnu/libpthread-2.23.so]
   427  /build/glibc-Cl5G7W/glibc-2.23/elf/../string/bits/string2.h:handle_ld_preload
   426  /build/glibc-Cl5G7W/glibc-2.23/malloc/malloc.c:malloc [/lib/x86_64-linux-gnu/libc-2.23.so]
   421  /build/glibc-Cl5G7W/glibc-2.23/malloc/malloc.c:realloc [/lib/x86_64-linux-gnu/libc-2.23.so]
   395  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-init.c:call_init.part.0 [/lib/x86_64-linux-gnu/ld-2.23.so]
   393  /build/glibc-Cl5G7W/glibc-2.23/nptl/libc_pthread_init.c:__libc_pthread_init [/lib/x86_64-linux-gnu/libc-2.23.so]
   382  /build/glibc-Cl5G7W/glibc-2.23/elf/../elf/dl-sysdep.c:_dl_sysdep_start [/lib/x86_64-linux-gnu/ld-2.23.so]
   354  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-load.c:_dl_init_paths [/lib/x86_64-linux-gnu/ld-2.23.so]
   352  /build/glibc-Cl5G7W/glibc-2.23/string/../bits/stdlib-bsearch.h:intel_check_word
   325  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-tls.c:_dl_allocate_tls_storage [/lib/x86_64-linux-gnu/ld-2.23.so]
   324  /build/glibc-Cl5G7W/glibc-2.23/stdlib/../stdlib/strtol.c:__strtoul_internal [/lib/x86_64-linux-gnu/libc-2.23.so]
   323  /build/glibc-Cl5G7W/glibc-2.23/elf/get-dynamic-info.h:dl_main
   319  /build/glibc-Cl5G7W/glibc-2.23/setjmp/../sysdeps/x86_64/setjmp.S:__sigsetjmp [/lib/x86_64-linux-gnu/libc-2.23.so]
   305  /build/glibc-Cl5G7W/glibc-2.23/nptl/pthread_mutex_unlock.c:pthread_mutex_unlock [/lib/x86_64-linux-gnu/libpthread-2.23.so]
   299  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-object.c:_dl_add_to_namespace_list [/lib/x86_64-linux-gnu/ld-2.23.so]
   286  /build/glibc-Cl5G7W/glibc-2.23/malloc/malloc.c:free [/lib/x86_64-linux-gnu/libc-2.23.so]
   280  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-hwcaps.c:_dl_important_hwcaps [/lib/x86_64-linux-gnu/ld-2.23.so]
   276  /build/glibc-Cl5G7W/glibc-2.23/stdlib/cxa_finalize.c:__cxa_finalize [/lib/x86_64-linux-gnu/libc-2.23.so]
   271  /build/glibc-Cl5G7W/glibc-2.23/malloc/malloc.c:_int_realloc [/lib/x86_64-linux-gnu/libc-2.23.so]
   254  /build/glibc-Cl5G7W/glibc-2.23/elf/get-dynamic-info.h:_dl_start
   248  /build/glibc-Cl5G7W/glibc-2.23/nptl/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:__libc_sigaction [/lib/x86_64-linux-gnu/libpthread-2.23.so]
   244  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-minimal.c:strsep [/lib/x86_64-linux-gnu/ld-2.23.so]
   238  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-deps.c:openaux [/lib/x86_64-linux-gnu/ld-2.23.so]
   184  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-lookup.c:_dl_setup_hash [/lib/x86_64-linux-gnu/ld-2.23.so]
   179  /build/glibc-Cl5G7W/glibc-2.23/malloc/arena.c:ptmalloc_init.part.5 [/lib/x86_64-linux-gnu/libc-2.23.so]
   168  /build/glibc-Cl5G7W/glibc-2.23/elf/../sysdeps/x86_64/dl-machine.h:_dl_start
   165  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-environ.c:_dl_next_ld_env_entry [/lib/x86_64-linux-gnu/ld-2.23.so]
   165  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-load.c:fillin_rpath [/lib/x86_64-linux-gnu/ld-2.23.so]
   164  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-minimal.c:malloc [/lib/x86_64-linux-gnu/ld-2.23.so]
   164  /build/glibc-Cl5G7W/glibc-2.23/nptl/nptl-init.c:__pthread_initialize_minimal [/lib/x86_64-linux-gnu/libpthread-2.23.so]
   159  /build/glibc-Cl5G7W/glibc-2.23/malloc/malloc.c:sysmalloc [/lib/x86_64-linux-gnu/libc-2.23.so]
   159  /build/glibc-Cl5G7W/glibc-2.23/string/../sysdeps/x86_64/cacheinfo.c:init_cacheinfo [/lib/x86_64-linux-gnu/libc-2.23.so]
   146  /build/glibc-Cl5G7W/glibc-2.23/elf/./dl-load.h:_dl_map_object_from_fd
   144  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-minimal.c:calloc [/lib/x86_64-linux-gnu/ld-2.23.so]
   144  /rustc/8a57831a4b7dfa960110599748f3b7382ae28237/src/liballoc/raw_vec.rs:main::main::hfe98083a4c87500f
   139  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-tls.c:_dl_allocate_tls_init [/lib/x86_64-linux-gnu/ld-2.23.so]
   138  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-open.c:_dl_find_dso_for_object [/lib/x86_64-linux-gnu/ld-2.23.so]
   138  /build/glibc-Cl5G7W/glibc-2.23/elf/../sysdeps/posix/dl-fileid.h:_dl_map_object_from_fd
   136  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-init.c:_dl_init [/lib/x86_64-linux-gnu/ld-2.23.so]
   131  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-version.c:_dl_check_all_versions [/lib/x86_64-linux-gnu/ld-2.23.so]
   127  ???:0x0000000000002a70 [/lib/x86_64-linux-gnu/libgcc_s.so.1]
   126  /build/glibc-Cl5G7W/glibc-2.23/string/strdup.c:strdup [/lib/x86_64-linux-gnu/ld-2.23.so]
   121  /build/glibc-Cl5G7W/glibc-2.23/elf/do-rel.h:_dl_start
   108  /build/glibc-Cl5G7W/glibc-2.23/libio/libioP.h:getdelim
   107  /build/glibc-Cl5G7W/glibc-2.23/io/../sysdeps/unix/syscall-template.S:open [/lib/x86_64-linux-gnu/ld-2.23.so]
   106  /build/glibc-Cl5G7W/glibc-2.23/elf/../sysdeps/x86/cpu-features.c:_dl_sysdep_start
   104  /build/glibc-Cl5G7W/glibc-2.23/elf/dl-tls.c:_dl_determine_tlsoffset [/lib/x86_64-linux-gnu/ld-2.23.so]
   101  /build/glibc-Cl5G7W/glibc-2.23/signal/../sysdeps/unix/sysv/linux/x86_64/sigaction.c:__libc_sigaction [/lib/x86_64-linux-gnu/libc-2.23.so]
    99  /build/glibc-Cl5G7W/glibc-2.23/elf/rtld.c:init_tls [/lib/x86_64-linux-gnu/ld-2.23.so]

and the input program is this:

pub fn main() {
    let mut v = Vec::new();
    for i in 0..10 {
        let a = i * 10;
        let b = a as f32;
        let c = b.sqrt() * a as f32;
        v.push(c.sqrt());
    }
    v = v.iter().map(|x| x * x).collect();
}
0 Likes

#13

oOf

0 Likes

#14

Good news, got it working, by using valgrind and callgrind_annotate!


You can see where the “hot” loops and lines are.

Something seems a little off with the amount of info it’s giving me, I’ll go back and check.

2 Likes

#15

Aha, it works! Profiling worked beautifully. The “hottest” function was a function called “stitch”:

Time to optimize that function.

Stitch basically merges a slice of a (custom) small vector implementation into a slice, so:

[[2, 3, 4], [2, 3]] would become [2, 3, 4, 2, 3], but the inner s are custom vectors. The iterator for that vector is pretty fast, so it’s probably something with repeatedly pushing objects to the value to_return. Any ideas on how to optimize that?

0 Likes

#16

Hmm, my eyes are seared but I came up with this:

fn stich<'a, T:Clone + util::Encodeable + util::Newable + Debug> (
    input: &[&'a util::NanoVec<T>],
) -> Vec<&'a T> {
    let to_return = input.map(|x| x.into_iter()).flatten();
    to_return.collect()
}

or perhaps this:

fn stich<'a, T:Clone + util::Encodeable + util::Newable + Debug> (
    input: &[&'a util::NanoVec<T>],
) -> Vec<&'a T> {
    let mut to_return = Vec::new();
    for i in input {
        to_return.extend(i);
    }
    to_return
}

as long at util::NanoVec<T> implements Deref<Target=[T]>

0 Likes

#17

Sorry about that (I presume it’s the light theme that seared your eyes - I keep my brightness on minimum. Lmao, if you think my terminal theme’s crazy, wait till you see my Vim theme:

Anyways, thanks for the help!

1 Like