Skip to content

Instantly share code, notes, and snippets.

@BigRedEye
Last active September 7, 2021 04:35
Show Gist options
  • Save BigRedEye/4cef5aeba06817780d403ef397829bdd to your computer and use it in GitHub Desktop.
Save BigRedEye/4cef5aeba06817780d403ef397829bdd to your computer and use it in GitHub Desktop.
Stupid driver

Rust is faster than {C,C++,You name it}

The benchmark itself is slow, actual difference in performance is much higher.

$ make benchmark
...
/usr/bin/clang++ --version
clang version 12.0.1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

/usr/bin/clang --version
clang version 12.0.1
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

rustc --version
rustc 1.54.0 (a178d0322 2021-07-26)
...
hyperfine \
	'benchmark/target/release/benchmark ./libmydriver-c.so' \
	'benchmark/target/release/benchmark ./libmydriver-c-fast.so' \
	'benchmark/target/release/benchmark ./libmydriver-cpp.so' \
	'benchmark/target/release/benchmark ./libmydriver-rs.so'
Benchmark #1: benchmark/target/release/benchmark ./libmydriver-c.so
  Time (mean ± σ):      1.417 s ±  0.015 s    [User: 1.415 s, System: 0.002 s]
  Range (min … max):    1.395 s …  1.452 s    10 runs
 
Benchmark #2: benchmark/target/release/benchmark ./libmydriver-c-fast.so
  Time (mean ± σ):     343.1 ms ±  19.8 ms    [User: 340.3 ms, System: 2.9 ms]
  Range (min … max):   321.7 ms … 376.5 ms    10 runs
 
Benchmark #3: benchmark/target/release/benchmark ./libmydriver-cpp.so
  Time (mean ± σ):     308.0 ms ±  15.3 ms    [User: 307.5 ms, System: 0.9 ms]
  Range (min … max):   290.5 ms … 338.2 ms    10 runs
 
Benchmark #4: benchmark/target/release/benchmark ./libmydriver-rs.so
  Time (mean ± σ):      1.249 s ±  0.026 s    [User: 1.249 s, System: 0.001 s]
  Range (min … max):    1.206 s …  1.276 s    10 runs
 
Summary
  'benchmark/target/release/benchmark ./libmydriver-cpp.so' ran
    1.11 ± 0.08 times faster than 'benchmark/target/release/benchmark ./libmydriver-c-fast.so'
    4.06 ± 0.22 times faster than 'benchmark/target/release/benchmark ./libmydriver-rs.so'
    4.60 ± 0.23 times faster than 'benchmark/target/release/benchmark ./libmydriver-c.so'

Building

Run make fold_dirs before build (gist does not support directories)

# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "benchmark"
version = "0.1.0"
dependencies = [
"libloading",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "libloading"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a"
dependencies = [
"cfg-if",
"winapi",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[package]
name = "benchmark"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
libloading = "0.7.0"
use libloading::{Library, Symbol};
#[derive(Debug)]
#[repr(C)]
struct Data {
port: [i8; 20],
status: i32,
value: [i8; 256],
}
type GetBulk = fn() -> i32;
type GetNextResult = fn() -> &'static Data;
fn benchmark(library_path: &str, iterations: u64) {
let lib = unsafe { Library::new(library_path) }.unwrap();
let get_bulk: Symbol<GetBulk> = unsafe { lib.get(b"get_bulk") }.unwrap();
let get_next_result: Symbol<GetNextResult> = unsafe { lib.get(b"get_next_result") }.unwrap();
let free_result: Symbol<fn()> = unsafe { lib.get(b"free_result") }.unwrap();
let start = std::time::Instant::now();
for _ in 0..iterations {
let count = get_bulk();
assert_eq!(count, 100);
for x in 0..count {
let data = get_next_result();
let port = unsafe { std::ffi::CStr::from_ptr(data.port.as_ptr()) }
.to_str()
.unwrap();
let value = unsafe { std::ffi::CStr::from_ptr(data.value.as_ptr()) }
.to_str()
.unwrap();
assert_eq!(data.status, x);
debug_assert_eq!(port, format!("PORT {}", x + 1));
debug_assert_eq!(value, format!("VALUE FOR {}", x + 1));
}
free_result();
}
let spent = start.elapsed();
println!(
"{}: {} ({} iters/s)",
library_path.rsplit("/").next().unwrap(),
spent.as_secs_f64(),
(iterations as f64 / spent.as_secs_f64()) as u64
);
}
fn main() {
for path in std::env::args().skip(1) {
benchmark(&path, 100000);
}
}
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Data {
char port[20];
int status;
char value[256];
};
struct Data *Result;
int current_result = 0;
static int itoa(int val, char* buf) {
const unsigned int radix = 10;
char* p;
unsigned int a; //every digit
int len;
char* b; //start of the digit char
char temp;
unsigned int u;
p = buf;
if (val < 0) {
*p++ = '-';
val = 0 - val;
}
u = (unsigned int)val;
b = p;
do {
a = u % radix;
u /= radix;
*p++ = a + '0';
} while (u > 0);
len = (int)(p - buf);
*p-- = 0;
//swap
do {
temp = *p;
*p = *b;
*b = temp;
--p;
++b;
} while (b < p);
return len;
}
static void fill_buf_impl(char* buf, char* prefix, size_t prefix_len, int value) {
memcpy(buf, prefix, prefix_len);
int len = itoa(value, buf + prefix_len);
buf[prefix_len + len] = '\0';
}
#define fill_buf(buf, str, value) fill_buf_impl(buf, str, sizeof(str) - 1, value);
int get_bulk() {
int n = 100;
Result = malloc(n * sizeof(struct Data));
for (int i=0; i<n; i++) {
int i_label = i + 1;
fill_buf(Result[i].port, "PORT ", i_label);
Result[i].status = i;
fill_buf(Result[i].value, "VALUE FOR ", i_label);
}
return n;
}
struct Data *get_next_result() {
return &Result[current_result++];
}
void free_result() {
free(Result);
current_result = 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Data {
char port[20];
int status;
char value[256];
};
struct Data *Result;
int current_result = 0;
int get_bulk() {
int n = 100;
Result = malloc(n * sizeof(struct Data));
for (int i=0; i<n; i++) {
int i_label = i + 1;
sprintf(Result[i].port, "PORT %u", i_label);
Result[i].status = i;
sprintf(Result[i].value, "VALUE FOR %u", i_label);
}
return n;
}
struct Data *get_next_result() {
return &Result[current_result++];
}
void free_result() {
free(Result);
current_result = 0;
}
#include <charconv>
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <cassert>
namespace {
struct Data {
char port[20];
int status;
char value[256];
};
struct Data *Result = nullptr;
int current_result = 0;
template <size_t N, size_t M>
size_t format_prefix(char (&buf)[N], const char (&prefix)[M], int value) {
constexpr size_t kPrefixSizeWithoutNul = M - 1;
std::memcpy(buf, prefix, kPrefixSizeWithoutNul);
auto [ptr, errc] = std::to_chars(buf + kPrefixSizeWithoutNul, buf + N, value);
assert(errc == std::errc{});
*ptr++ = '\0';
return ptr - buf;
}
} // namespace
extern "C" int get_bulk() {
int n = 100;
Result = (Data*)std::malloc(sizeof(Data) * n);
for (int i = 0; i < n; i++) {
int i_label = i + 1;
Result[i].status = i;
format_prefix(Result[i].port, "PORT ", i_label);
format_prefix(Result[i].value, "VALUE FOR ", i_label);
}
return n;
}
extern "C" Data *get_next_result() {
return &Result[current_result++];
}
extern "C" void free_result() {
std::free(Result);
current_result = 0;
}
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "driver_rs"
version = "0.1.0"
[package]
name = "driver_rs"
version = "0.1.0"
edition = "2018"
[lib]
crate-type = ["cdylib"]
bench = false
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
/* build with
cargo build --release
*/
type PortName = [i8; 20];
type StateStatus = i32;
type StateValue = [i8; 256];
#[derive(Debug)]
#[repr(C)]
pub struct Data {
port: PortName,
status: StateStatus,
value: StateValue,
}
impl Data {
fn new() -> Self {
Self {
port: [0; 20],
status: -0xff,
value: [0; 256],
}
}
}
struct DataResult {
data: Vec<Data>,
current: usize,
}
impl DataResult {
unsafe fn get_next(&mut self) -> &Data {
match self.data.get(self.current) {
Some(v) => {
self.current += 1;
v
}
None => panic!("Result overflow"),
}
}
fn clear(&mut self) {
self.data.clear();
self.current = 0;
}
}
fn fill_c_string(s: &str, buf: &mut [i8]) {
let b = s.as_bytes();
if b.len() > buf.len() - 1 {
panic!("string overflow");
} else {
for i in 0..b.len() {
buf[i] = b[i] as i8;
}
buf[b.len()] = 0;
}
}
static mut D: DataResult = DataResult {
data: Vec::new(),
current: 0,
};
#[no_mangle]
pub unsafe fn get_bulk() -> i32 {
let n = 100;
D.clear();
for i in 0..n {
let i_label = i + 1;
let mut d = Data::new();
d.status = i;
fill_c_string(&format!("PORT {}", i_label), &mut d.port);
fill_c_string(&format!("VALUE FOR {}", i_label), &mut d.value);
D.data.push(d);
}
n
}
#[no_mangle]
pub unsafe fn get_next_result<'a>() -> &'a Data {
D.get_next()
}
#[no_mangle]
pub unsafe fn free_result() {
D.clear();
}
#!/usr/bin/env bash
case $1 in
pack)
PACKED=`echo $2 | sed -s 's@/@%@g'`
mv $2 $PACKED
;;
unpack)
UNPACKED=`echo $2 | sed -s 's@%@/@g'`
mkdir -p `dirname $UNPACKED`
mv $2 $UNPACKED
;;
esac
flatten_dirs:
find . -type f -wholename '*/*' -not -path './.git/*' | sed 's@^\./@@g' | grep / | xargs -n1 ./gistify.sh pack
fold_dirs:
ls | grep '%' | xargs -n1 ./gistify.sh unpack
driver_c:
$(CC) -c driver.c -o driver-c.o -Wall -Werror -fpic -std=c17 -O3
$(CC) driver-c.o -o libmydriver-c.so -shared -O3
rm driver-c.o
driver_c_fast:
$(CC) -c driver-fast.c -o driver-c-fast.o -Wall -Werror -fpic -std=c17 -O3
$(CC) driver-c-fast.o -o libmydriver-c-fast.so -shared -O3
rm driver-c-fast.o
driver_cpp:
$(CXX) -c driver.cpp -o driver-cxx.o -Wall -Werror -fpic -std=c++20 -O3
$(CXX) driver-cxx.o -o libmydriver-cpp.so -shared -O3
rm driver-cxx.o
driver_rust:
cd driver_rs && cargo build --release
cp driver_rs/target/release/libdriver_rs.so libmydriver-rs.so
bench:
cd benchmark && cargo build --release
clean:
rm *.so
rm -rf driver_rs/target
rm -rf benchmark/target
rm -rf perf/data
build: driver_rust driver_c driver_c_fast driver_cpp bench
versions:
$(CXX) --version
$(CC) --version
rustc --version
hyperfine: build versions
hyperfine \
'benchmark/target/release/benchmark ./libmydriver-c.so' \
'benchmark/target/release/benchmark ./libmydriver-c-fast.so' \
'benchmark/target/release/benchmark ./libmydriver-cpp.so' \
'benchmark/target/release/benchmark ./libmydriver-rs.so'
perf_record: build
mkdir -p perf/data
perf record -o perf/data/c -g --call-graph=dwarf -F500 -- benchmark/target/release/benchmark ./libmydriver-c.so
perf record -o perf/data/c-fast -g --call-graph=dwarf -F500 -- benchmark/target/release/benchmark ./libmydriver-c-fast.so
perf record -o perf/data/cpp -g --call-graph=dwarf -F500 -- benchmark/target/release/benchmark ./libmydriver-cpp.so
perf record -o perf/data/rs -g --call-graph=dwarf -F500 -- benchmark/target/release/benchmark ./libmydriver-rs.so
perf_flamegraph: perf_record
mkdir -p perf/svg
perf script -i perf/data/c | stackcollapse-perf.pl | flamegraph.pl > perf/svg/c.svg
perf script -i perf/data/c-fast | stackcollapse-perf.pl | flamegraph.pl > perf/svg/c-fast.svg
perf script -i perf/data/cpp | stackcollapse-perf.pl | flamegraph.pl > perf/svg/cpp.svg
perf script -i perf/data/rs | stackcollapse-perf.pl | flamegraph.pl > perf/svg/rs.svg
Display the source blob
Display the rendered blob
Raw
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" width="1200" height="326" onload="init(evt)" viewBox="0 0 1200 326" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Flame graph stack visualization. See https://github.com/brendangregg/FlameGraph for latest version, and http://www.brendangregg.com/flamegraphs.html for examples. -->
<!-- NOTES: -->
<defs >
<linearGradient id="background" y1="0" y2="1" x1="0" x2="0" >
<stop stop-color="#eeeeee" offset="5%" />
<stop stop-color="#eeeeb0" offset="95%" />
</linearGradient>
</defs>
<style type="text/css">
.func_g:hover { stroke:black; stroke-width:0.5; cursor:pointer; }
</style>
<script type="text/ecmascript">
<![CDATA[
var details, searchbtn, matchedtxt, svg;
function init(evt) {
details = document.getElementById("details").firstChild;
searchbtn = document.getElementById("search");
matchedtxt = document.getElementById("matched");
svg = document.getElementsByTagName("svg")[0];
searching = 0;
}
// mouse-over for info
function s(node) { // show
info = g_to_text(node);
details.nodeValue = "Function: " + info;
}
function c() { // clear
details.nodeValue = ' ';
}
// ctrl-F for search
window.addEventListener("keydown",function (e) {
if (e.keyCode === 114 || (e.ctrlKey && e.keyCode === 70)) {
e.preventDefault();
search_prompt();
}
})
// functions
function find_child(parent, name, attr) {
var children = parent.childNodes;
for (var i=0; i<children.length;i++) {
if (children[i].tagName == name)
return (attr != undefined) ? children[i].attributes[attr].value : children[i];
}
return;
}
function orig_save(e, attr, val) {
if (e.attributes["_orig_"+attr] != undefined) return;
if (e.attributes[attr] == undefined) return;
if (val == undefined) val = e.attributes[attr].value;
e.setAttribute("_orig_"+attr, val);
}
function orig_load(e, attr) {
if (e.attributes["_orig_"+attr] == undefined) return;
e.attributes[attr].value = e.attributes["_orig_"+attr].value;
e.removeAttribute("_orig_"+attr);
}
function g_to_text(e) {
var text = find_child(e, "title").firstChild.nodeValue;
return (text)
}
function g_to_func(e) {
var func = g_to_text(e);
// if there's any manipulation we want to do to the function
// name before it's searched, do it here before returning.
return (func);
}
function update_text(e) {
var r = find_child(e, "rect");
var t = find_child(e, "text");
var w = parseFloat(r.attributes["width"].value) -3;
var txt = find_child(e, "title").textContent.replace(/\([^(]*\)$/,"");
t.attributes["x"].value = parseFloat(r.attributes["x"].value) +3;
// Smaller than this size won't fit anything
if (w < 2*12*0.59) {
t.textContent = "";
return;
}
t.textContent = txt;
// Fit in full text width
if (/^ *$/.test(txt) || t.getSubStringLength(0, txt.length) < w)
return;
for (var x=txt.length-2; x>0; x--) {
if (t.getSubStringLength(0, x+2) <= w) {
t.textContent = txt.substring(0,x) + "..";
return;
}
}
t.textContent = "";
}
// zoom
function zoom_reset(e) {
if (e.attributes != undefined) {
orig_load(e, "x");
orig_load(e, "width");
}
if (e.childNodes == undefined) return;
for(var i=0, c=e.childNodes; i<c.length; i++) {
zoom_reset(c[i]);
}
}
function zoom_child(e, x, ratio) {
if (e.attributes != undefined) {
if (e.attributes["x"] != undefined) {
orig_save(e, "x");
e.attributes["x"].value = (parseFloat(e.attributes["x"].value) - x - 10) * ratio + 10;
if(e.tagName == "text") e.attributes["x"].value = find_child(e.parentNode, "rect", "x") + 3;
}
if (e.attributes["width"] != undefined) {
orig_save(e, "width");
e.attributes["width"].value = parseFloat(e.attributes["width"].value) * ratio;
}
}
if (e.childNodes == undefined) return;
for(var i=0, c=e.childNodes; i<c.length; i++) {
zoom_child(c[i], x-10, ratio);
}
}
function zoom_parent(e) {
if (e.attributes) {
if (e.attributes["x"] != undefined) {
orig_save(e, "x");
e.attributes["x"].value = 10;
}
if (e.attributes["width"] != undefined) {
orig_save(e, "width");
e.attributes["width"].value = parseInt(svg.width.baseVal.value) - (10*2);
}
}
if (e.childNodes == undefined) return;
for(var i=0, c=e.childNodes; i<c.length; i++) {
zoom_parent(c[i]);
}
}
function zoom(node) {
var attr = find_child(node, "rect").attributes;
var width = parseFloat(attr["width"].value);
var xmin = parseFloat(attr["x"].value);
var xmax = parseFloat(xmin + width);
var ymin = parseFloat(attr["y"].value);
var ratio = (svg.width.baseVal.value - 2*10) / width;
// XXX: Workaround for JavaScript float issues (fix me)
var fudge = 0.0001;
var unzoombtn = document.getElementById("unzoom");
unzoombtn.style["opacity"] = "1.0";
var el = document.getElementsByTagName("g");
for(var i=0;i<el.length;i++){
var e = el[i];
var a = find_child(e, "rect").attributes;
var ex = parseFloat(a["x"].value);
var ew = parseFloat(a["width"].value);
// Is it an ancestor
if (0 == 0) {
var upstack = parseFloat(a["y"].value) > ymin;
} else {
var upstack = parseFloat(a["y"].value) < ymin;
}
if (upstack) {
// Direct ancestor
if (ex <= xmin && (ex+ew+fudge) >= xmax) {
e.style["opacity"] = "0.5";
zoom_parent(e);
e.onclick = function(e){unzoom(); zoom(this);};
update_text(e);
}
// not in current path
else
e.style["display"] = "none";
}
// Children maybe
else {
// no common path
if (ex < xmin || ex + fudge >= xmax) {
e.style["display"] = "none";
}
else {
zoom_child(e, xmin, ratio);
e.onclick = function(e){zoom(this);};
update_text(e);
}
}
}
}
function unzoom() {
var unzoombtn = document.getElementById("unzoom");
unzoombtn.style["opacity"] = "0.0";
var el = document.getElementsByTagName("g");
for(i=0;i<el.length;i++) {
el[i].style["display"] = "block";
el[i].style["opacity"] = "1";
zoom_reset(el[i]);
update_text(el[i]);
}
}
// search
function reset_search() {
var el = document.getElementsByTagName("rect");
for (var i=0; i < el.length; i++) {
orig_load(el[i], "fill")
}
}
function search_prompt() {
if (!searching) {
var term = prompt("Enter a search term (regexp " +
"allowed, eg: ^ext4_)", "");
if (term != null) {
search(term)
}
} else {
reset_search();
searching = 0;
searchbtn.style["opacity"] = "0.1";
searchbtn.firstChild.nodeValue = "Search"
matchedtxt.style["opacity"] = "0.0";
matchedtxt.firstChild.nodeValue = ""
}
}
function search(term) {
var re = new RegExp(term);
var el = document.getElementsByTagName("g");
var matches = new Object();
var maxwidth = 0;
for (var i = 0; i < el.length; i++) {
var e = el[i];
if (e.attributes["class"].value != "func_g")
continue;
var func = g_to_func(e);
var rect = find_child(e, "rect");
if (rect == null) {
// the rect might be wrapped in an anchor
// if nameattr href is being used
if (rect = find_child(e, "a")) {
rect = find_child(r, "rect");
}
}
if (func == null || rect == null)
continue;
// Save max width. Only works as we have a root frame
var w = parseFloat(rect.attributes["width"].value);
if (w > maxwidth)
maxwidth = w;
if (func.match(re)) {
// highlight
var x = parseFloat(rect.attributes["x"].value);
orig_save(rect, "fill");
rect.attributes["fill"].value =
"rgb(230,0,230)";
// remember matches
if (matches[x] == undefined) {
matches[x] = w;
} else {
if (w > matches[x]) {
// overwrite with parent
matches[x] = w;
}
}
searching = 1;
}
}
if (!searching)
return;
searchbtn.style["opacity"] = "1.0";
searchbtn.firstChild.nodeValue = "Reset Search"
// calculate percent matched, excluding vertical overlap
var count = 0;
var lastx = -1;
var lastw = 0;
var keys = Array();
for (k in matches) {
if (matches.hasOwnProperty(k))
keys.push(k);
}
// sort the matched frames by their x location
// ascending, then width descending
keys.sort(function(a, b){
return a - b;
});
// Step through frames saving only the biggest bottom-up frames
// thanks to the sort order. This relies on the tree property
// where children are always smaller than their parents.
var fudge = 0.0001; // JavaScript floating point
for (var k in keys) {
var x = parseFloat(keys[k]);
var w = matches[keys[k]];
if (x >= lastx + lastw - fudge) {
count += w;
lastx = x;
lastw = w;
}
}
// display matched percent
matchedtxt.style["opacity"] = "1.0";
pct = 100 * count / maxwidth;
if (pct == 100)
pct = "100"
else
pct = pct.toFixed(1)
matchedtxt.firstChild.nodeValue = "Matched: " + pct + "%";
}
function searchover(e) {
searchbtn.style["opacity"] = "1.0";
}
function searchout(e) {
if (searching) {
searchbtn.style["opacity"] = "1.0";
} else {
searchbtn.style["opacity"] = "0.1";
}
}
]]>
</script>
<rect x="0.0" y="0" width="1200.0" height="326.0" fill="url(#background)" />
<text text-anchor="middle" x="600.00" y="24" font-size="17" font-family="Verdana" fill="rgb(0,0,0)" >Flame Graph</text>
<text text-anchor="" x="10.00" y="309" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" id="details" > </text>
<text text-anchor="" x="10.00" y="24" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" id="unzoom" onclick="unzoom()" style="opacity:0.0;cursor:pointer" >Reset Zoom</text>
<text text-anchor="" x="1090.00" y="24" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" id="search" onmouseover="searchover()" onmouseout="searchout()" onclick="search_prompt()" style="opacity:0.1;cursor:pointer" >Search</text>
<text text-anchor="" x="1090.00" y="309" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" id="matched" > </text>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>core::str::converts::from_utf8 (7 samples, 3.35%)</title><rect x="10.0" y="229" width="39.5" height="15.0" fill="rgb(240,155,42)" rx="2" ry="2" />
<text text-anchor="" x="13.00" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >cor..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>[[stack]] (6 samples, 2.87%)</title><rect x="89.0" y="245" width="33.9" height="15.0" fill="rgb(247,119,14)" rx="2" ry="2" />
<text text-anchor="" x="92.04" y="255.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >[[..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::ffi::c_str::CStr::from_ptr (1 samples, 0.48%)</title><rect x="49.5" y="229" width="5.7" height="15.0" fill="rgb(207,213,47)" rx="2" ry="2" />
<text text-anchor="" x="52.52" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>_dl_sysdep_start (1 samples, 0.48%)</title><rect x="1184.4" y="213" width="5.6" height="15.0" fill="rgb(234,173,48)" rx="2" ry="2" />
<text text-anchor="" x="1187.35" y="223.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>core::str::validations::run_utf8_validation (71 samples, 33.97%)</title><rect x="777.8" y="37" width="400.9" height="15.0" fill="rgb(252,81,48)" rx="2" ry="2" />
<text text-anchor="" x="780.85" y="47.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >core::str::validations::run_utf8_validation</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>[[heap]] (14 samples, 6.70%)</title><rect x="10.0" y="245" width="79.0" height="15.0" fill="rgb(222,210,40)" rx="2" ry="2" />
<text text-anchor="" x="13.00" y="255.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >[[heap]]</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>alloc_perturb (1 samples, 0.48%)</title><rect x="156.8" y="229" width="5.6" height="15.0" fill="rgb(215,10,0)" rx="2" ry="2" />
<text text-anchor="" x="159.79" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::ffi::c_str::CStr::to_str (6 samples, 2.87%)</title><rect x="55.2" y="229" width="33.8" height="15.0" fill="rgb(222,97,46)" rx="2" ry="2" />
<text text-anchor="" x="58.17" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >st..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::sys_common::backtrace::__rust_begin_short_backtrace (176 samples, 84.21%)</title><rect x="190.7" y="101" width="993.7" height="15.0" fill="rgb(212,141,8)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="111.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >std::sys_common::backtrace::__rust_begin_short_backtrace</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>main (176 samples, 84.21%)</title><rect x="190.7" y="213" width="993.7" height="15.0" fill="rgb(229,187,24)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="223.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >main</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::ffi::c_str::CStr::to_bytes (1 samples, 0.48%)</title><rect x="1178.7" y="53" width="5.7" height="15.0" fill="rgb(232,105,47)" rx="2" ry="2" />
<text text-anchor="" x="1181.71" y="63.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::ffi::c_str::CStr::from_ptr (2 samples, 0.96%)</title><rect x="106.0" y="229" width="11.3" height="15.0" fill="rgb(207,128,46)" rx="2" ry="2" />
<text text-anchor="" x="108.98" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>get_bulk (47 samples, 22.49%)</title><rect x="207.6" y="69" width="265.4" height="15.0" fill="rgb(245,32,12)" rx="2" ry="2" />
<text text-anchor="" x="210.61" y="79.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >get_bulk</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::ffi::c_str::CStr::to_str (1 samples, 0.48%)</title><rect x="117.3" y="229" width="5.6" height="15.0" fill="rgb(212,228,6)" rx="2" ry="2" />
<text text-anchor="" x="120.27" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>get_next_result (6 samples, 2.87%)</title><rect x="473.0" y="69" width="33.8" height="15.0" fill="rgb(236,192,4)" rx="2" ry="2" />
<text text-anchor="" x="475.97" y="79.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >ge..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>[unknown] (7 samples, 3.35%)</title><rect x="122.9" y="245" width="39.5" height="15.0" fill="rgb(219,111,42)" rx="2" ry="2" />
<text text-anchor="" x="125.92" y="255.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >[un..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::ffi::c_str::CStr::to_str (99 samples, 47.37%)</title><rect x="625.4" y="69" width="559.0" height="15.0" fill="rgb(240,37,54)" rx="2" ry="2" />
<text text-anchor="" x="628.41" y="79.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >std::ffi::c_str::CStr::to_str</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>core::str::converts::from_utf8 (17 samples, 8.13%)</title><rect x="681.9" y="37" width="95.9" height="15.0" fill="rgb(250,31,9)" rx="2" ry="2" />
<text text-anchor="" x="684.87" y="47.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >core::str::..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>__strlen_avx2 (21 samples, 10.05%)</title><rect x="506.8" y="53" width="118.6" height="15.0" fill="rgb(215,120,8)" rx="2" ry="2" />
<text text-anchor="" x="509.84" y="63.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >__strlen_avx2</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>__libc_start_main (176 samples, 84.21%)</title><rect x="190.7" y="229" width="993.7" height="15.0" fill="rgb(222,167,7)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >__libc_start_main</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>itoa (28 samples, 13.40%)</title><rect x="314.9" y="37" width="158.1" height="15.0" fill="rgb(223,178,13)" rx="2" ry="2" />
<text text-anchor="" x="317.88" y="47.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >itoa</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>__libc_start_main (6 samples, 2.87%)</title><rect x="122.9" y="229" width="33.9" height="15.0" fill="rgb(216,23,1)" rx="2" ry="2" />
<text text-anchor="" x="125.92" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >__..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>all (209 samples, 100%)</title><rect x="10.0" y="277" width="1180.0" height="15.0" fill="rgb(226,115,36)" rx="2" ry="2" />
<text text-anchor="" x="13.00" y="287.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::panicking::try::do_call (176 samples, 84.21%)</title><rect x="190.7" y="149" width="993.7" height="15.0" fill="rgb(230,212,9)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="159.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >std::panicking::try::do_call</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>_start (182 samples, 87.08%)</title><rect x="162.4" y="245" width="1027.6" height="15.0" fill="rgb(217,158,26)" rx="2" ry="2" />
<text text-anchor="" x="165.44" y="255.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >_start</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::rt::lang_start_internal (176 samples, 84.21%)</title><rect x="190.7" y="197" width="993.7" height="15.0" fill="rgb(205,215,14)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="207.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >std::rt::lang_start_internal</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>_dl_start (1 samples, 0.48%)</title><rect x="1184.4" y="229" width="5.6" height="15.0" fill="rgb(236,185,30)" rx="2" ry="2" />
<text text-anchor="" x="1187.35" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>[libpthread-2.33.so] (6 samples, 2.87%)</title><rect x="122.9" y="213" width="33.9" height="15.0" fill="rgb(214,161,2)" rx="2" ry="2" />
<text text-anchor="" x="125.92" y="223.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >[l..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>__GI___tunables_init (1 samples, 0.48%)</title><rect x="1184.4" y="197" width="5.6" height="15.0" fill="rgb(254,148,7)" rx="2" ry="2" />
<text text-anchor="" x="1187.35" y="207.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>fill_buf_impl (43 samples, 20.57%)</title><rect x="230.2" y="53" width="242.8" height="15.0" fill="rgb(222,0,10)" rx="2" ry="2" />
<text text-anchor="" x="233.19" y="63.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >fill_buf_impl</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::ffi::c_str::CStr::from_ptr (21 samples, 10.05%)</title><rect x="506.8" y="69" width="118.6" height="15.0" fill="rgb(230,157,0)" rx="2" ry="2" />
<text text-anchor="" x="509.84" y="79.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >std::ffi::c_st..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>core::ops::function::impls::&lt;impl core::ops::function::FnOnce&lt;A&gt; for &amp;F&gt;::call_once (176 samples, 84.21%)</title><rect x="190.7" y="133" width="993.7" height="15.0" fill="rgb(238,30,31)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="143.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >core::ops::function::impls::&lt;impl core::ops::function::FnOnce&lt;A&gt; for &amp;F&gt;::call_once</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::panic::catch_unwind (176 samples, 84.21%)</title><rect x="190.7" y="181" width="993.7" height="15.0" fill="rgb(244,25,22)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="191.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >std::panic::catch_unwind</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>benchmark::main (6 samples, 2.87%)</title><rect x="122.9" y="197" width="33.9" height="15.0" fill="rgb(246,149,28)" rx="2" ry="2" />
<text text-anchor="" x="125.92" y="207.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >be..</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>core::str::converts::from_utf8 (3 samples, 1.44%)</title><rect x="89.0" y="229" width="17.0" height="15.0" fill="rgb(248,57,50)" rx="2" ry="2" />
<text text-anchor="" x="92.04" y="239.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" ></text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>benchmark::main (176 samples, 84.21%)</title><rect x="190.7" y="85" width="993.7" height="15.0" fill="rgb(228,151,17)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="95.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >benchmark::main</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::panicking::try (176 samples, 84.21%)</title><rect x="190.7" y="165" width="993.7" height="15.0" fill="rgb(252,132,19)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="175.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >std::panicking::try</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hf7071dbb0abde613 (176 samples, 84.21%)</title><rect x="190.7" y="117" width="993.7" height="15.0" fill="rgb(242,31,9)" rx="2" ry="2" />
<text text-anchor="" x="193.67" y="127.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >std::rt::lang_start::_$u7b$$u7b$closure$u7d$$u7d$::hf7071dbb0abde613</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>core::str::converts::from_utf8 (98 samples, 46.89%)</title><rect x="625.4" y="53" width="553.3" height="15.0" fill="rgb(237,158,13)" rx="2" ry="2" />
<text text-anchor="" x="628.41" y="63.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >core::str::converts::from_utf8</text>
</g>
<g class="func_g" onmouseover="s(this)" onmouseout="c()" onclick="zoom(this)">
<title>benchmark (209 samples, 100.00%)</title><rect x="10.0" y="261" width="1180.0" height="15.0" fill="rgb(227,101,26)" rx="2" ry="2" />
<text text-anchor="" x="13.00" y="271.5" font-size="12" font-family="Verdana" fill="rgb(0,0,0)" >benchmark</text>
</g>
</svg>
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment