Skip to content

Commit

Permalink
Merge pull request #536 from metrico/feature/export_pprof
Browse files Browse the repository at this point in the history
Feature/export pprof
  • Loading branch information
akvlad authored Jul 17, 2024
2 parents 37097df + fc89e36 commit 6500fa3
Show file tree
Hide file tree
Showing 10 changed files with 1,424 additions and 252 deletions.
2 changes: 2 additions & 0 deletions pyroscope/pprof-bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ bytes = "1.5.0"
prost = "0.12.3"
json = "0.12.4"
lazy_static = "1.4.0"
bytemuck = "1.16.1"

# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires
# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for
# code size when deploying.
console_error_panic_hook = { version = "0.1.7", optional = true }
base64 = "0.22.1"

[dev-dependencies]
wasm-bindgen-test = "0.3.34"
Expand Down
11 changes: 9 additions & 2 deletions pyroscope/pprof-bin/pkg/pprof_bin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@ export function merge_prof(id: number, bytes: Uint8Array, sample_type: string):
/**
* @param {number} id
* @param {Uint8Array} bytes
* @param {string} sample_type
*/
export function merge_tree(id: number, bytes: Uint8Array): void;
export function merge_tree(id: number, bytes: Uint8Array, sample_type: string): void;
/**
* @param {number} id
* @param {string} sample_type
* @returns {Uint8Array}
*/
export function export_tree(id: number, sample_type: string): Uint8Array;
/**
* @param {Uint8Array} payload
* @returns {Uint8Array}
*/
export function export_tree(id: number): Uint8Array;
export function export_trees_pprof(payload: Uint8Array): Uint8Array;
/**
* @param {number} id
*/
Expand Down
38 changes: 32 additions & 6 deletions pyroscope/pprof-bin/pkg/pprof_bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,14 @@ module.exports.merge_prof = function(id, bytes, sample_type) {
/**
* @param {number} id
* @param {Uint8Array} bytes
* @param {string} sample_type
*/
module.exports.merge_tree = function(id, bytes) {
module.exports.merge_tree = function(id, bytes, sample_type) {
const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.merge_tree(id, ptr0, len0);
const ptr1 = passStringToWasm0(sample_type, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
wasm.merge_tree(id, ptr0, len0, ptr1, len1);
};

let cachedInt32Memory0 = null;
Expand All @@ -132,17 +135,40 @@ function getArrayU8FromWasm0(ptr, len) {
}
/**
* @param {number} id
* @param {string} sample_type
* @returns {Uint8Array}
*/
module.exports.export_tree = function(id, sample_type) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
const ptr0 = passStringToWasm0(sample_type, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
wasm.export_tree(retptr, id, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var v2 = getArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1, 1);
return v2;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
};

/**
* @param {Uint8Array} payload
* @returns {Uint8Array}
*/
module.exports.export_tree = function(id) {
module.exports.export_trees_pprof = function(payload) {
try {
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
wasm.export_tree(retptr, id);
const ptr0 = passArray8ToWasm0(payload, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.export_trees_pprof(retptr, ptr0, len0);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var v1 = getArrayU8FromWasm0(r0, r1).slice();
var v2 = getArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1, 1);
return v1;
return v2;
} finally {
wasm.__wbindgen_add_to_stack_pointer(16);
}
Expand Down
Binary file modified pyroscope/pprof-bin/pkg/pprof_bin_bg.wasm
Binary file not shown.
5 changes: 3 additions & 2 deletions pyroscope/pprof-bin/pkg/pprof_bin_bg.wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
/* eslint-disable */
export const memory: WebAssembly.Memory;
export function merge_prof(a: number, b: number, c: number, d: number, e: number): void;
export function merge_tree(a: number, b: number, c: number): void;
export function export_tree(a: number, b: number): void;
export function merge_tree(a: number, b: number, c: number, d: number, e: number): void;
export function export_tree(a: number, b: number, c: number, d: number): void;
export function export_trees_pprof(a: number, b: number, c: number): void;
export function drop_tree(a: number): void;
export function init_panic_hook(): void;
export function __wbindgen_malloc(a: number, b: number): number;
Expand Down
154 changes: 75 additions & 79 deletions pyroscope/pprof-bin/src/ch64.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,39 @@

pub fn read_uint64_le(bytes: &[u8]) -> (u64) {
pub fn read_uint64_le(bytes: &[u8]) -> u64 {
let mut res: u64 = 0;
for i in 0..8 {
res |= (bytes[i] as u64) << (i * 8);
}
res
}

const kMul: u64 = 0x9ddfea08eb382d69;
const K_MUL: u64 = 0x9ddfea08eb382d69;

pub fn hash_128_to_64(l: u64, h: u64) -> u64 {
let mut a = (l ^ h).wrapping_mul(kMul);
a ^= (a >> 47);
let mut b = (h ^ a).wrapping_mul(kMul);
b ^= (b >> 47);
b = b.wrapping_mul(kMul);
let mut a = (l ^ h).wrapping_mul(K_MUL);
a ^= a >> 47;
let mut b = (h ^ a).wrapping_mul(K_MUL);
b ^= b >> 47;
b = b.wrapping_mul(K_MUL);
b
}

const k0: u64 = 0xc3a5c85c97cb3127;
const k2: u64 = 0x9ae16a3b2f90404f;
const k1: u64 = 0xb492b66fbe98f273;
const k3: u64 = 0xc949d7c7509e6557;
const K0: u64 = 0xc3a5c85c97cb3127;
const K2: u64 = 0x9ae16a3b2f90404f;
const K1: u64 = 0xb492b66fbe98f273;
const K3: u64 = 0xc949d7c7509e6557;
fn ch16(u: u64, v: u64) -> u64 {
hash_128_to_64(u, v)
}

fn rot64(val: u64, shift: usize) -> u64 {
if shift == 0 {
return val
return val;
}
return (val >> shift) | val<<(64-shift)
return (val >> shift) | val << (64 - shift);
}

fn shiftMix(val: u64) -> u64 {
return val ^ (val >> 47)
fn shift_mix(val: u64) -> u64 {
return val ^ (val >> 47);
}

fn hash16(u: u64, v: u64) -> u64 {
Expand All @@ -51,131 +50,128 @@ fn fetch32(p: &[u8]) -> u32 {

fn ch33to64(s: &[u8], length: usize) -> u64 {
let mut z = read_uint64_le(&s[24..]);
let mut a = read_uint64_le(&s) +
(length as u64+read_uint64_le(&s[length-16..])).wrapping_mul(k0);
let mut b = rot64(a+z, 52);
let mut c= rot64(a, 37);
let mut a =
read_uint64_le(&s) + (length as u64 + read_uint64_le(&s[length - 16..])).wrapping_mul(K0);
let mut b = rot64(a + z, 52);
let mut c = rot64(a, 37);
a += read_uint64_le(&s[8..]);
c += rot64(a, 7);
a += read_uint64_le(&s[16..]);
let vf= a + z;
let vs= b + rot64(a, 31) + c;
let vf = a + z;
let vs = b + rot64(a, 31) + c;

a = read_uint64_le(&s[16..]) + read_uint64_le(&s[length-32..]);
z = read_uint64_le(&s[length-8..]);
b = rot64(a+z, 52);
a = read_uint64_le(&s[16..]) + read_uint64_le(&s[length - 32..]);
z = read_uint64_le(&s[length - 8..]);
b = rot64(a + z, 52);
c = rot64(a, 37);
a += read_uint64_le(&s[length-24..]);
a += read_uint64_le(&s[length - 24..]);
c += rot64(a, 7);
a += read_uint64_le(&s[length-16..]);
a += read_uint64_le(&s[length - 16..]);

let wf= a + z;
let ws= b + rot64(a, 31) + c;
let r= shiftMix((vf+ws).wrapping_mul(k2) + (wf+vs).wrapping_mul(k0));
return shiftMix(r.wrapping_mul(k0)+vs).wrapping_mul(k2)
let wf = a + z;
let ws = b + rot64(a, 31) + c;
let r = shift_mix((vf + ws).wrapping_mul(K2) + (wf + vs).wrapping_mul(K0));
return shift_mix(r.wrapping_mul(K0) + vs).wrapping_mul(K2);
}

fn ch17to32(s: &[u8], length: usize) -> u64 {
let a = read_uint64_le(s).wrapping_mul(k1);
let b= read_uint64_le(&s[8..]);
let c= read_uint64_le(&s[length-8..]).wrapping_mul(k2);
let d= read_uint64_le(&s[length-16..]).wrapping_mul(k0);
let a = read_uint64_le(s).wrapping_mul(K1);
let b = read_uint64_le(&s[8..]);
let c = read_uint64_le(&s[length - 8..]).wrapping_mul(K2);
let d = read_uint64_le(&s[length - 16..]).wrapping_mul(K0);
return hash16(
rot64(a-b, 43)+rot64(c, 30)+d,
a+rot64(b^k3, 20)-c+(length as u64),
)
rot64(a - b, 43) + rot64(c, 30) + d,
a + rot64(b ^ K3, 20) - c + (length as u64),
);
}

fn ch0to16(s: &[u8], length: usize) -> u64 {
if length > 8 {
let a = read_uint64_le(s);
let b= read_uint64_le(&s[length-8..]);
return ch16(a, rot64(b+(length as u64), (length))) ^ b;
let b = read_uint64_le(&s[length - 8..]);
return ch16(a, rot64(b + (length as u64), length)) ^ b;
}
if length >= 4 {
let a = (fetch32(s) as u64);
return ch16((length as u64)+(a<<3), (fetch32(&s[length-4..]) as u64));
let a = fetch32(s) as u64;
return ch16((length as u64) + (a << 3), fetch32(&s[length - 4..]) as u64);
}
if length > 0 {
let a = s[0];
let b = s[length>>1];
let c= s[length-1];
let b = s[length >> 1];
let c = s[length - 1];
let y = (a as u32) + ((b as u32) << 8);
let z = (length as u32) + ((c as u32) << 2);
return shiftMix(
(y as u64).wrapping_mul(k2)^
(z as u64).wrapping_mul(k3))
.wrapping_mul(k2);
return shift_mix((y as u64).wrapping_mul(K2) ^ (z as u64).wrapping_mul(K3))
.wrapping_mul(K2);
}
return k2
return K2;
}

fn weakHash32Seeds(w: u64, x: u64, y: u64, z: u64, _a: u64, _b: u64) -> (u64, u64) {
fn weak_hash32_seeds(w: u64, x: u64, y: u64, z: u64, _a: u64, _b: u64) -> (u64, u64) {
let mut a = _a + w;
let mut b = rot64(_b+a+z, 21);
let mut b = rot64(_b + a + z, 21);
let c = a;
a += x;
a += y;
b += rot64(a, 44);
return (a+z, b+c)
return (a + z, b + c);
}

// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
fn weakHash32SeedsByte(s: &[u8], a: u64, b: u64) -> (u64, u64) {
fn weak_hash32_seeds_byte(s: &[u8], a: u64, b: u64) -> (u64, u64) {
_ = s[31];
return weakHash32Seeds(
read_uint64_le(&s[0..0+8]),
read_uint64_le(&s[8..8+8]),
read_uint64_le(&s[16..16+8]),
read_uint64_le(&s[24..24+8]),
return weak_hash32_seeds(
read_uint64_le(&s[0..0 + 8]),
read_uint64_le(&s[8..8 + 8]),
read_uint64_le(&s[16..16 + 8]),
read_uint64_le(&s[24..24 + 8]),
a,
b,
);
}

fn nearestMultiple64(b: &[u8]) -> usize {
fn nearest_multiple_64(b: &[u8]) -> usize {
return ((b.len()) - 1) & !63;
}

// CH64 returns ClickHouse version of Hash64.
pub fn city_hash_64(s: &[u8]) -> u64 {
let length = s.len();
if length <= 16 {
return ch0to16(s, length)
return ch0to16(s, length);
}
if length <= 32 {
return ch17to32(s, length)
return ch17to32(s, length);
}
if length <= 64 {
return ch33to64(s, length)
return ch33to64(s, length);
}

let x= read_uint64_le(s);
let y= read_uint64_le(&s[length-16..]) ^ k1;
let mut z = read_uint64_le(&s[length-56..]) ^ k0;
let x = read_uint64_le(s);
let y = read_uint64_le(&s[length - 16..]) ^ K1;
let mut z = read_uint64_le(&s[length - 56..]) ^ K0;

let mut v= weakHash32SeedsByte(&s[length-64..], (length as u64), y);
let mut w= weakHash32SeedsByte(&s[length-32..], (length as u64).wrapping_mul(k1), k0);
z += shiftMix(v.1).wrapping_mul(k1);
let mut x = rot64(z+x, 39).wrapping_mul(k1);
let mut y = rot64(y, 33).wrapping_mul(k1);
let mut v = weak_hash32_seeds_byte(&s[length - 64..], length as u64, y);
let mut w = weak_hash32_seeds_byte(&s[length - 32..], (length as u64).wrapping_mul(K1), K0);
z += shift_mix(v.1).wrapping_mul(K1);
let mut x = rot64(z + x, 39).wrapping_mul(K1);
let mut y = rot64(y, 33).wrapping_mul(K1);
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
let mut _s = &s[..nearestMultiple64(s)];
let mut _s = &s[..nearest_multiple_64(s)];
while _s.len() > 0 {
x = rot64(x+y+v.0+read_uint64_le(&s[16..]), 37).wrapping_mul(k1);
y = rot64(y+v.1+read_uint64_le(&s[48..]), 42).wrapping_mul(k1);
x = rot64(x + y + v.0 + read_uint64_le(&s[16..]), 37).wrapping_mul(K1);
y = rot64(y + v.1 + read_uint64_le(&s[48..]), 42).wrapping_mul(K1);
x ^= w.1;
y ^= v.0;

z = rot64(z^w.0, 33);
v = weakHash32SeedsByte(s, v.1.wrapping_mul(k1), x+w.0);
w = weakHash32SeedsByte(&s[32..], z+w.1, y);
z = rot64(z ^ w.0, 33);
v = weak_hash32_seeds_byte(s, v.1.wrapping_mul(K1), x + w.0);
w = weak_hash32_seeds_byte(&s[32..], z + w.1, y);
(z, x) = (x, z);
_s = &_s[64..];
}
return ch16(
ch16(v.0, w.0)+shiftMix(y).wrapping_mul(k1)+z,
ch16(v.1, w.1)+x,
ch16(v.0, w.0) + shift_mix(y).wrapping_mul(K1) + z,
ch16(v.1, w.1) + x,
);
}

Loading

0 comments on commit 6500fa3

Please sign in to comment.