Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/export pprof #536

Merged
merged 8 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading