Skip to content

Commit

Permalink
Merge pull request #468 from metrico/prof_improvements
Browse files Browse the repository at this point in the history
Prof improvements
  • Loading branch information
akvlad authored Feb 19, 2024
2 parents f447475 + b53e279 commit a1c6af8
Show file tree
Hide file tree
Showing 9 changed files with 696 additions and 198 deletions.
52 changes: 50 additions & 2 deletions lib/db/maintain/scripts.js
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,42 @@ module.exports.profiles = [
key,
val,
cityHash64(val) % 50000 as val_id
FROM profiles_series_gin`
FROM profiles_series_gin`,

`ALTER TABLE profiles_input {{{OnCluster}}}
ADD COLUMN IF NOT EXISTS \`tree\` Array(Tuple(UInt64, UInt64, UInt64, Array(Tuple(String, Int64, Int64)))),
ADD COLUMN IF NOT EXISTS \`functions\` Array(Tuple(UInt64, String))`,

`ALTER TABLE profiles {{{OnCluster}}}
ADD COLUMN IF NOT EXISTS \`tree\` Array(Tuple(UInt64, UInt64, UInt64, Array(Tuple(String, Int64, Int64)))),
ADD COLUMN IF NOT EXISTS \`functions\` Array(Tuple(UInt64, String))`,

'RENAME TABLE IF EXISTS profiles_mv TO profiles_mv_bak {{{OnCluster}}}',

`CREATE MATERIALIZED VIEW IF NOT EXISTS profiles_mv {{{OnCluster}}} TO profiles AS
SELECT
timestamp_ns,
cityHash64(arraySort(arrayConcat(
profiles_input.tags, [
('__type__', concatWithSeparator(':', type, period_type, period_unit) as _type_id),
('__sample_types_units__', arrayStringConcat(arrayMap(x -> x.1 || ':' || x.2, arraySort(sample_types_units)), ';')),
('service_name', service_name)
])) as _tags) as fingerprint,
_type_id as type_id,
sample_types_units,
service_name,
duration_ns,
payload_type,
payload,
values_agg,
tree,
functions
FROM profiles_input`,

'DROP TABLE IF EXISTS profiles_mv_bak {{{OnCluster}}}',

"INSERT INTO settings (fingerprint, type, name, value, inserted_at) VALUES (cityHash64('profiles_v2'), 'update', " +
"'profiles_v2', toString(toUnixTimestamp(NOW())), NOW())"
]

module.exports.profiles_dist = [
Expand Down Expand Up @@ -427,5 +462,18 @@ module.exports.profiles_dist = [
key String,
val String,
val_id UInt64
) ENGINE = Distributed('{{CLUSTER}}','{{DB}}','profiles_series_keys', rand());`
) ENGINE = Distributed('{{CLUSTER}}','{{DB}}','profiles_series_keys', rand());`,

`ALTER TABLE profiles_dist {{{OnCluster}}}
ADD COLUMN IF NOT EXISTS \`tree\` Array(Tuple(UInt64, UInt64, UInt64, Array(Tuple(String, Int64, Int64)))),
ADD COLUMN IF NOT EXISTS \`functions\` Array(Tuple(UInt64, String))`,

`ALTER TABLE profiles_dist {{{OnCluster}}}
ADD COLUMN IF NOT EXISTS \`sample_types_units\` Array(Tuple(String, String))`,

`ALTER TABLE profiles_series_dist {{{OnCluster}}}
ADD COLUMN IF NOT EXISTS \`sample_types_units\` Array(Tuple(String, String))`,

`ALTER TABLE profiles_series_gin_dist {{{OnCluster}}}
ADD COLUMN IF NOT EXISTS \`sample_types_units\` Array(Tuple(String, String))`
]
6 changes: 6 additions & 0 deletions pyroscope/pprof-bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ authors = ["[email protected]"]
edition = "2018"
build = "build.rs"


[lib]
crate-type = ["cdylib", "rlib"]

Expand All @@ -30,6 +31,11 @@ wasm-bindgen-test = "0.3.34"
[profile.release]
# Tell `rustc` to optimize for small code size.
opt-level = "s"
overflow-checks = false

[profile.dev]
overflow-checks = false


[build-dependencies]
prost-build = { version = "0.12.3" }
Expand Down
10 changes: 7 additions & 3 deletions pyroscope/pprof-bin/pkg/pprof_bin.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
* @param {Uint8Array} bytes
* @param {string} sample_type
*/
export function merge_tree(id: number, bytes: Uint8Array, sample_type: string): void;
export function merge_prof(id: number, bytes: Uint8Array, sample_type: string): void;
/**
* @param {number} id
* @param {Uint8Array} bytes
*/
export function merge_tree(id: number, bytes: Uint8Array): void;
/**
* @param {number} id
* @param {string} sample_type
* @returns {Uint8Array}
*/
export function export_tree(id: number, sample_type: string): Uint8Array;
export function export_tree(id: number): Uint8Array;
/**
* @param {number} id
*/
Expand Down
26 changes: 17 additions & 9 deletions pyroscope/pprof-bin/pkg/pprof_bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ function passStringToWasm0(arg, malloc, realloc) {
const ret = encodeString(arg, view);

offset += ret.written;
ptr = realloc(ptr, len, offset, 1) >>> 0;
}

WASM_VECTOR_LEN = offset;
Expand All @@ -98,12 +99,22 @@ function passStringToWasm0(arg, malloc, realloc) {
* @param {Uint8Array} bytes
* @param {string} sample_type
*/
module.exports.merge_tree = function(id, bytes, sample_type) {
module.exports.merge_prof = function(id, bytes, sample_type) {
const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
const ptr1 = passStringToWasm0(sample_type, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len1 = WASM_VECTOR_LEN;
wasm.merge_tree(id, ptr0, len0, ptr1, len1);
wasm.merge_prof(id, ptr0, len0, ptr1, len1);
};

/**
* @param {number} id
* @param {Uint8Array} bytes
*/
module.exports.merge_tree = function(id, bytes) {
const ptr0 = passArray8ToWasm0(bytes, wasm.__wbindgen_malloc);
const len0 = WASM_VECTOR_LEN;
wasm.merge_tree(id, ptr0, len0);
};

let cachedInt32Memory0 = null;
Expand All @@ -121,20 +132,17 @@ function getArrayU8FromWasm0(ptr, len) {
}
/**
* @param {number} id
* @param {string} sample_type
* @returns {Uint8Array}
*/
module.exports.export_tree = function(id, sample_type) {
module.exports.export_tree = function(id) {
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);
wasm.export_tree(retptr, id);
var r0 = getInt32Memory0()[retptr / 4 + 0];
var r1 = getInt32Memory0()[retptr / 4 + 1];
var v2 = getArrayU8FromWasm0(r0, r1).slice();
var v1 = getArrayU8FromWasm0(r0, r1).slice();
wasm.__wbindgen_free(r0, r1 * 1, 1);
return v2;
return v1;
} 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
@@ -1,8 +1,9 @@
/* tslint:disable */
/* eslint-disable */
export const memory: WebAssembly.Memory;
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 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 drop_tree(a: number): void;
export function init_panic_hook(): void;
export function __wbindgen_malloc(a: number, b: number): number;
Expand Down
181 changes: 181 additions & 0 deletions pyroscope/pprof-bin/src/ch64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@

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;

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);
b
}

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 >> shift) | val<<(64-shift)
}

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

fn hash16(u: u64, v: u64) -> u64 {
hash_128_to_64(u, v)
}

fn fetch32(p: &[u8]) -> u32 {
let mut res: u32 = 0;
for i in 0..4 {
res |= (p[i] as u32) << (i * 8);
}
res
}

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);
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;

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..]);
c += rot64(a, 7);
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)
}

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);
return hash16(
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;
}
if length >= 4 {
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 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 k2
}

fn weakHash32Seeds(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 c = a;
a += x;
a += y;
b += rot64(a, 44);
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) {
_ = 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]),
a,
b,
);
}

fn nearestMultiple64(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)
}
if length <= 32 {
return ch17to32(s, length)
}
if length <= 64 {
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 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);
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
let mut _s = &s[..nearestMultiple64(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 ^= 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, 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,
);
}

Loading

0 comments on commit a1c6af8

Please sign in to comment.