UBERF-7428: Fix memory issues (#5940)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev
2024-06-28 22:21:28 +07:00
committed by GitHub
parent 3394d1ad82
commit 51383caa92
22 changed files with 303 additions and 191 deletions
+99 -74
View File
@@ -38,6 +38,7 @@ import { Worker, isMainThread, parentPort } from 'worker_threads'
import { CSVWriter } from './csv'
interface StartMessage {
email: string
workspaceId: WorkspaceId
transactorUrl: string
id: number
@@ -54,6 +55,7 @@ interface StartMessage {
// If enabled, will perform write tx for same values and Derived format.
write: boolean
sleep: number
mode: 'find-all' | 'connect-only'
}
binary: boolean
compression: boolean
@@ -75,8 +77,17 @@ interface PendingMsg extends Msg {
export async function benchmark (
workspaceId: WorkspaceId[],
users: Map<string, string[]>,
transactorUrl: string,
cmd: { from: number, steps: number, sleep: number, binary: boolean, write: boolean, compression: boolean }
cmd: {
from: number
steps: number
sleep: number
binary: boolean
write: boolean
compression: boolean
mode: 'find-all' | 'connect-only'
}
): Promise<void> {
const operating = new Set<string>()
const workers: Worker[] = []
@@ -278,7 +289,9 @@ export async function benchmark (
.map((it) => {
const wsid = workspaceId[randNum(workspaceId.length)]
const workId = 'w-' + i + '-' + it
const wsUsers = users.get(wsid.name) ?? []
const msg: StartMessage = {
email: wsUsers[randNum(wsUsers.length)],
workspaceId: wsid,
transactorUrl,
id: i,
@@ -293,7 +306,8 @@ export async function benchmark (
rand: 512
},
sleep: cmd.sleep,
write: cmd.write
write: cmd.write,
mode: cmd.mode
},
binary: cmd.binary,
compression: cmd.compression
@@ -339,81 +353,91 @@ export function benchmarkWorker (): void {
setMetadata(client.metadata.UseProtocolCompression, msg.compression)
console.log('connecting to', msg.workspaceId)
connection = await connect(msg.transactorUrl, msg.workspaceId, undefined)
const opt = new TxOperations(connection, (core.account.System + '_benchmark') as Ref<Account>)
parentPort?.postMessage({
type: 'operate',
workId: msg.workId
})
connection = await connect(msg.transactorUrl, msg.workspaceId, msg.email)
const rateLimiter = new RateLimiter(msg.options.rate)
let bigRunning = 0
while (msg.options.smallRequests + msg.options.bigRequests > 0) {
const variant = Math.random()
// console.log(`Thread ${msg.workId} ${msg.options.smallRequests} ${msg.options.bigRequests}`)
if (msg.options.bigRequests > 0 && variant < 0.5 && bigRunning === 0) {
await rateLimiter.add(async () => {
bigRunning = 1
await connection?.findAll(core.class.BenchmarkDoc, {
source: msg.workId,
request: {
documents: {
from: 1024,
to: 1000
},
size: {
// 1kb to 5kb
from: 1 * 1024,
to: 4 * 1024
}
}
})
})
bigRunning = 0
msg.options.bigRequests--
}
if (msg.options.smallRequests > 0 && variant > 0.5) {
await rateLimiter.add(async () => {
await connection?.findAll(core.class.BenchmarkDoc, {
source: msg.workId,
request: {
documents: {
from: msg.options.limit.min,
to: msg.options.limit.min + msg.options.limit.rand
},
size: {
from: 4,
to: 16
}
}
})
})
msg.options.smallRequests--
}
if (msg.options.write) {
await opt.updateDoc(core.class.BenchmarkDoc, core.space.DerivedTx, '' as Ref<BenchmarkDoc>, {
response: 'qwe'
})
}
if (msg.options.sleep > 0) {
await new Promise((resolve) => setTimeout(resolve, randNum(msg.options.sleep)))
}
}
// clearInterval(infoInterval)
await rateLimiter.waitProcessing()
const to1 = setTimeout(() => {
if (msg.options.mode === 'find-all') {
const opt = new TxOperations(connection, (core.account.System + '_benchmark') as Ref<Account>)
parentPort?.postMessage({
type: 'log',
workId: msg.workId,
msg: `timeout waiting processing${msg.workId}`
type: 'operate',
workId: msg.workId
})
}, 5000)
clearTimeout(to1)
//
// console.log(`${msg.idd} perform complete`)
const rateLimiter = new RateLimiter(msg.options.rate)
let bigRunning = 0
while (msg.options.smallRequests + msg.options.bigRequests > 0) {
const variant = Math.random()
// console.log(`Thread ${msg.workId} ${msg.options.smallRequests} ${msg.options.bigRequests}`)
if (msg.options.bigRequests > 0 && variant < 0.5 && bigRunning === 0) {
await rateLimiter.add(async () => {
bigRunning = 1
await connection?.findAll(core.class.BenchmarkDoc, {
source: msg.workId,
request: {
documents: {
from: 1024,
to: 1000
},
size: {
// 1kb to 5kb
from: 1 * 1024,
to: 4 * 1024
}
}
})
})
bigRunning = 0
msg.options.bigRequests--
}
if (msg.options.smallRequests > 0 && variant > 0.5) {
await rateLimiter.add(async () => {
await connection?.findAll(core.class.BenchmarkDoc, {
source: msg.workId,
request: {
documents: {
from: msg.options.limit.min,
to: msg.options.limit.min + msg.options.limit.rand
},
size: {
from: 4,
to: 16
}
}
})
})
msg.options.smallRequests--
}
if (msg.options.write) {
await opt.updateDoc(core.class.BenchmarkDoc, core.space.DerivedTx, '' as Ref<BenchmarkDoc>, {
response: 'qwe'
})
}
if (msg.options.sleep > 0) {
await new Promise((resolve) => setTimeout(resolve, randNum(msg.options.sleep)))
}
}
// clearInterval(infoInterval)
await rateLimiter.waitProcessing()
const to1 = setTimeout(() => {
parentPort?.postMessage({
type: 'log',
workId: msg.workId,
msg: `timeout waiting processing${msg.workId}`
})
}, 5000)
clearTimeout(to1)
//
// console.log(`${msg.idd} perform complete`)
} else if (msg.options.mode === 'connect-only') {
parentPort?.postMessage({
type: 'operate',
workId: msg.workId
})
// Just a huge timeout
await new Promise<void>((resolve) => setTimeout(resolve, 50000000))
}
} catch (err: any) {
console.error(msg.workspaceId, err)
} finally {
@@ -427,6 +451,7 @@ export function benchmarkWorker (): void {
await connection?.close()
clearTimeout(to)
}
parentPort?.postMessage({
type: 'complete',
workId: msg.workId
+39 -8
View File
@@ -1018,6 +1018,7 @@ export function devTool (
.option('--compression <compression>', 'Use protocol compression', false)
.option('--write <write>', 'Perform write operations', false)
.option('--workspaces <workspaces>', 'Workspaces to test on, comma separated', '')
.option('--mode <mode>', 'A benchmark mode. Supported values: `find-all`, `connect-only` ', 'find-all')
.action(
async (cmd: {
from: string
@@ -1027,20 +1028,50 @@ export function devTool (
binary: string
compression: string
write: string
mode: 'find-all' | 'connect-only'
}) => {
console.log(JSON.stringify(cmd))
await benchmark(
cmd.workspaces.split(',').map((it) => getWorkspaceId(it, productId)),
transactorUrl,
{
const { mongodbUri } = prepareTools()
await withDatabase(mongodbUri, async (db, client) => {
console.log(JSON.stringify(cmd))
if (!['find-all', 'connect-only'].includes(cmd.mode)) {
console.log('wrong mode')
return
}
const allWorkspacesPure = Array.from(await listWorkspacesPure(db, productId))
const allWorkspaces = new Map(allWorkspacesPure.map((it) => [it.workspace, it]))
let workspaces = cmd.workspaces
.split(',')
.map((it) => it.trim())
.filter((it) => it.length > 0)
.map((it) => getWorkspaceId(it, productId))
if (cmd.workspaces.length === 0) {
workspaces = allWorkspacesPure.map((it) => getWorkspaceId(it.workspace, productId))
}
const accounts = new Map(Array.from(await listAccounts(db)).map((it) => [it._id.toString(), it.email]))
const accountWorkspaces = new Map<string, string[]>()
for (const ws of workspaces) {
const wsInfo = allWorkspaces.get(ws.name)
if (wsInfo !== undefined) {
accountWorkspaces.set(
ws.name,
wsInfo.accounts.map((it) => accounts.get(it.toString()) as string)
)
}
}
await benchmark(workspaces, accountWorkspaces, transactorUrl, {
steps: parseInt(cmd.steps),
from: parseInt(cmd.from),
sleep: parseInt(cmd.sleep),
binary: cmd.binary === 'true',
compression: cmd.compression === 'true',
write: cmd.write === 'true'
}
)
write: cmd.write === 'true',
mode: cmd.mode
})
})
}
)
program