Skip to content

Commit fa3e67d

Browse files
committed
render-diff endpoint impl
1 parent decb26c commit fa3e67d

12 files changed

+585
-61
lines changed
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use crate::pattern::Pattern;
2+
use uuid::Uuid;
3+
4+
pub struct PatternRegistry {
5+
patterns: Vec<Pattern>,
6+
}
7+
8+
impl PatternRegistry {
9+
pub const fn new() -> PatternRegistry {
10+
PatternRegistry { patterns: Vec::new() }
11+
}
12+
13+
pub fn find_pattern(&mut self, str_text: &Vec<String>, i_text: &Vec<u64>, sample: String) -> &Pattern {
14+
let mut idx: i32 = -1;
15+
let mut mtc = 0;
16+
for i in 0..self.patterns.len() {
17+
mtc = self.patterns[i].match_text(&i_text);
18+
if mtc == -1 || mtc > self.patterns[i].fluct {
19+
continue;
20+
}
21+
idx = i as i32;
22+
break;
23+
}
24+
25+
if idx == -1 {
26+
let pattern = Pattern::new(Uuid::new_v4().to_string(), &i_text, &str_text, sample);
27+
self.patterns.push(pattern);
28+
idx = (self.patterns.len() - 1) as i32;
29+
} else if mtc != 0 {
30+
self.patterns[idx as usize].adjust_pattern(&i_text);
31+
}
32+
return &self.patterns[idx as usize];
33+
}
34+
35+
pub fn to_string(&self) -> String {
36+
let mut s = String::new();
37+
for i in 0..self.patterns.len() {
38+
s += self.patterns[i].to_string().as_str();
39+
s += "\n";
40+
}
41+
return s
42+
}
43+
}
44+
45+
pub static mut REGISTRY: PatternRegistry = PatternRegistry::new();

patterns/patterns_bin/src/tokens.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use regex::{Regex, CaptureMatches, Match};
2+
3+
/*pub fn tokenize(re: &Regex, text: &str) -> CaptureMatches {
4+
return re.captures_iter(text);
5+
}*/
6+
7+
pub struct Tokenizer<'a> {
8+
text: String,
9+
pos: usize,
10+
re: Regex,
11+
iter: Option<CaptureMatches<'a, 'a>>
12+
}
13+
14+
impl Tokenizer<'_> {
15+
pub fn new<'a>(text: &'a str) -> Tokenizer<'a> {
16+
let mut res = Tokenizer {
17+
text: text.to_string(),
18+
pos: 0,
19+
re: Regex::new(r"([\p{L}_]+|[\d.]+|[^\p{L}_\d.]+)\s*").unwrap(),
20+
iter: None
21+
};
22+
res
23+
}
24+
}
25+
26+
impl Iterator for Tokenizer<'_> {
27+
type Item = String;
28+
29+
fn next(&mut self) -> Option<Self::Item> {
30+
None
31+
/*let cap: Option<Match> = None;
32+
if let Some(c) = cap {
33+
self.pos += c.get(0).unwrap().end();
34+
Some(c.get(0).unwrap().as_str().to_string())
35+
} else {
36+
None
37+
}*/
38+
}
39+
}
40+
41+
#[test]
42+
fn test_tokenizer() {
43+
let text = "Hello, world! 123";
44+
let mut tokenizer = Tokenizer::new(text);
45+
}

pyroscope/flamebearer.d.ts

+13
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,16 @@ export interface heatmap {
5252
minDepth: uint64,
5353
maxDepth: uint64
5454
}
55+
56+
export interface level {
57+
values: number[]
58+
}
59+
60+
export interface flamegraphDiff {
61+
name: string[],
62+
levels: level[],
63+
total: int64,
64+
maxSelf: int64,
65+
leftTicks: int64,
66+
rightTicks: int64
67+
}

pyroscope/merge_stack_traces.js

+32-22
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@ const sqlWithReference = (ref) => {
2222

2323
let ctxIdx = 0
2424

25-
const mergeStackTraces = async (typeRegex, sel, fromTimeSec, toTimeSec, log) => {
25+
const newCtxIdx = () => ++ctxIdx
26+
27+
const importStackTraces = async (typeRegex, sel, fromTimeSec, toTimeSec, log, _ctxIdx, save) => {
2628
const dist = clusterName ? '_dist' : ''
2729
const v2 = checkVersion('profiles_v2', (fromTimeSec - 3600) * 1000)
2830
const serviceNameSelector = serviceNameSelectorQuery(sel)
@@ -127,30 +129,36 @@ const mergeStackTraces = async (typeRegex, sel, fromTimeSec, toTimeSec, log) =>
127129
const binData = Uint8Array.from(profiles.data)
128130
log.debug(`selectMergeStacktraces: profiles downloaded: ${binData.length / 1025}kB in ${Date.now() - start}ms`)
129131
require('./pprof-bin/pkg/pprof_bin').init_panic_hook()
130-
const _ctxIdx = ++ctxIdx
131132
const [legacyLen, shift] = readULeb32(binData, 0)
132133
let ofs = shift
133-
try {
134-
let mergePprofLat = BigInt(0)
135-
for (let i = 0; i < legacyLen; i++) {
136-
const [profLen, shift] = readULeb32(binData, ofs)
137-
ofs += shift
138-
start = process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)
139-
pprofBin.merge_prof(_ctxIdx,
140-
Uint8Array.from(profiles.data.slice(ofs, ofs + profLen)),
141-
`${typeRegex.sampleType}:${typeRegex.sampleUnit}`)
142-
mergePprofLat += (process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)) - start
143-
ofs += profLen
144-
}
145-
start = process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)
146-
pprofBin.merge_tree(_ctxIdx, Uint8Array.from(profiles.data.slice(ofs)),
147-
typeRegex.sampleType + ':' + typeRegex.sampleUnit)
148-
const mergeTreeLat = (process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)) - start
134+
let mergePprofLat = BigInt(0)
135+
for (let i = 0; i < legacyLen; i++) {
136+
const [profLen, shift] = readULeb32(binData, ofs)
137+
ofs += shift
149138
start = process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)
139+
pprofBin.merge_prof(_ctxIdx,
140+
Uint8Array.from(profiles.data.slice(ofs, ofs + profLen)),
141+
`${typeRegex.sampleType}:${typeRegex.sampleUnit}`)
142+
mergePprofLat += (process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)) - start
143+
ofs += profLen
144+
}
145+
start = process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)
146+
save && require('fs').writeFileSync(`/home/hromozeka/QXIP/qryn/data.${Date.now()}.bin`,
147+
Buffer.from(Uint8Array.from(profiles.data.slice(ofs))))
148+
pprofBin.merge_tree(_ctxIdx, Uint8Array.from(profiles.data.slice(ofs)),
149+
typeRegex.sampleType + ':' + typeRegex.sampleUnit)
150+
const mergeTreeLat = (process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)) - start
151+
log.debug(`merge_pprof: ${mergePprofLat / BigInt(1000000)}ms`)
152+
log.debug(`merge_tree: ${mergeTreeLat / BigInt(1000000)}ms`)
153+
}
154+
155+
const mergeStackTraces = async (typeRegex, sel, fromTimeSec, toTimeSec, log) => {
156+
const _ctxIdx = newCtxIdx()
157+
try {
158+
await importStackTraces(typeRegex, sel, fromTimeSec, toTimeSec, log, _ctxIdx)
159+
const start = process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)
150160
const resp = pprofBin.export_tree(_ctxIdx, typeRegex.sampleType + ':' + typeRegex.sampleUnit)
151161
const exportTreeLat = (process.hrtime?.bigint ? process.hrtime.bigint() : BigInt(0)) - start
152-
log.debug(`merge_pprof: ${mergePprofLat / BigInt(1000000)}ms`)
153-
log.debug(`merge_tree: ${mergeTreeLat / BigInt(1000000)}ms`)
154162
log.debug(`export_tree: ${exportTreeLat / BigInt(1000000)}ms`)
155163
return Buffer.from(resp)
156164
} finally {
@@ -159,5 +167,7 @@ const mergeStackTraces = async (typeRegex, sel, fromTimeSec, toTimeSec, log) =>
159167
}
160168

161169
module.exports = {
162-
mergeStackTraces
163-
}
170+
mergeStackTraces,
171+
importStackTraces,
172+
newCtxIdx
173+
}

pyroscope/pprof-bin/pkg/pprof_bin.d.ts

+7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ export function merge_prof(id: number, bytes: Uint8Array, sample_type: string):
1313
*/
1414
export function merge_tree(id: number, bytes: Uint8Array, sample_type: string): void;
1515
/**
16+
* @param {number} id1
17+
* @param {number} id2
18+
* @param {string} sample_type
19+
* @returns {Uint8Array}
20+
*/
21+
export function diff_tree(id1: number, id2: number, sample_type: string): Uint8Array;
22+
/**
1623
* @param {number} id
1724
* @param {string} sample_type
1825
* @returns {Uint8Array}

pyroscope/pprof-bin/pkg/pprof_bin.js

+22
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,28 @@ function getArrayU8FromWasm0(ptr, len) {
133133
ptr = ptr >>> 0;
134134
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
135135
}
136+
/**
137+
* @param {number} id1
138+
* @param {number} id2
139+
* @param {string} sample_type
140+
* @returns {Uint8Array}
141+
*/
142+
module.exports.diff_tree = function(id1, id2, sample_type) {
143+
try {
144+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
145+
const ptr0 = passStringToWasm0(sample_type, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
146+
const len0 = WASM_VECTOR_LEN;
147+
wasm.diff_tree(retptr, id1, id2, ptr0, len0);
148+
var r0 = getInt32Memory0()[retptr / 4 + 0];
149+
var r1 = getInt32Memory0()[retptr / 4 + 1];
150+
var v2 = getArrayU8FromWasm0(r0, r1).slice();
151+
wasm.__wbindgen_free(r0, r1 * 1, 1);
152+
return v2;
153+
} finally {
154+
wasm.__wbindgen_add_to_stack_pointer(16);
155+
}
156+
};
157+
136158
/**
137159
* @param {number} id
138160
* @param {string} sample_type
27.5 KB
Binary file not shown.

pyroscope/pprof-bin/pkg/pprof_bin_bg.wasm.d.ts

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
export const memory: WebAssembly.Memory;
44
export function merge_prof(a: number, b: number, c: number, d: number, e: number): void;
55
export function merge_tree(a: number, b: number, c: number, d: number, e: number): void;
6+
export function diff_tree(a: number, b: number, c: number, d: number, e: number): void;
67
export function export_tree(a: number, b: number, c: number, d: number): void;
78
export function export_trees_pprof(a: number, b: number, c: number): void;
89
export function drop_tree(a: number): void;

0 commit comments

Comments
 (0)