Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/database/conat/leak-search.ts
1503 views
1
/*
2
Code for testing for memory leaks. As of this commit, nothing tested for here
3
leaks memory in my dev setup.
4
5
USAGE:
6
7
Run with an account_id from your dev server and pass the expose-gc flag so the
8
gc command is defined:
9
10
11
ACCOUNT_ID="6aae57c6-08f1-4bb5-848b-3ceb53e61ede" DEBUG=cocalc:* DEBUG_CONSOLE=yes node --expose-gc
12
13
Then do this
14
15
a = require('@cocalc/database/conat/leak-search')
16
await a.testQueryOnly(50)
17
await a.testChangefeed(50)
18
19
Do a test multiple times to see if there is a real leak, e.g., the following is GOOD:
20
21
> a.testChangefeed(50)
22
Promise {
23
<pending>,
24
[Symbol(async_id_symbol)]: 47,
25
[Symbol(trigger_async_id_symbol)]: 6
26
}
27
> leaked 5.209536 MB
28
29
> a.testChangefeed(50)
30
Promise {
31
<pending>,
32
[Symbol(async_id_symbol)]: 3167,
33
[Symbol(trigger_async_id_symbol)]: 6
34
}
35
> leaked -0.029184 MB <--- GOOD!
36
*/
37
38
import { db } from "@cocalc/database";
39
import { uuid } from "@cocalc/util/misc";
40
import { delay } from "awaiting";
41
import { callback2 } from "@cocalc/util/async-utils";
42
43
// set env variable to an account_id on your dev server with lots of projects.
44
const ACCOUNT_ID = process.env.ACCOUNT_ID;
45
46
export function create({ id, cb }: { id; cb? }) {
47
const d = db();
48
d.user_query({
49
query: {
50
projects_all: [
51
{ project_id: null, title: null, state: null, status: null },
52
],
53
},
54
changes: id,
55
account_id: ACCOUNT_ID,
56
cb: (err) => {
57
cb?.(err);
58
cb = undefined;
59
},
60
});
61
}
62
63
export function cancel(id) {
64
db().user_query_cancel_changefeed({ id });
65
}
66
67
let pre: any = { heapUsed: 0 };
68
async function before() {
69
gc?.();
70
await delay(500);
71
gc?.();
72
pre = process.memoryUsage();
73
}
74
75
async function after() {
76
gc?.();
77
await delay(500);
78
gc?.();
79
const post = process.memoryUsage();
80
const leak = (post.heapUsed - pre.heapUsed) / 10 ** 6;
81
console.log("leaked", leak, "MB");
82
return leak;
83
}
84
85
// This leaks horribly
86
export async function testChangefeed(n) {
87
await before();
88
for (let i = 0; i < n; i++) {
89
const id = uuid();
90
await callback2(create, { id });
91
cancel(id);
92
}
93
return await after();
94
}
95
96
// query only does NOT leak
97
export async function testQueryOnly(n) {
98
await before();
99
for (let i = 0; i < n; i++) {
100
const d = db();
101
await callback2(d.user_query, {
102
query: {
103
projects_all: [
104
{ project_id: null, title: null, state: null, status: null },
105
],
106
},
107
account_id: "6aae57c6-08f1-4bb5-848b-3ceb53e61ede",
108
});
109
}
110
return await after();
111
}
112
113