From a6b272f9ce9e40f29c63ce3c374ee44a10396ef9 Mon Sep 17 00:00:00 2001 From: Mathias Jakobsen Date: Mon, 4 Dec 2023 09:22:39 +0000 Subject: [PATCH] Merge pull request #15991 from overleaf/mj-doc-updater-benchmark [document-updater] Add script for benchmarking apply function GitOrigin-RevId: acb8174eec9d28870f05cca4802621f8f0c8a9bd --- services/document-updater/benchmarks/apply.js | 78 +++++++++++++++++++ services/document-updater/package.json | 1 + 2 files changed, 79 insertions(+) create mode 100644 services/document-updater/benchmarks/apply.js diff --git a/services/document-updater/benchmarks/apply.js b/services/document-updater/benchmarks/apply.js new file mode 100644 index 0000000000..24676784f4 --- /dev/null +++ b/services/document-updater/benchmarks/apply.js @@ -0,0 +1,78 @@ +const text = require('../app/js/sharejs/types/text.js') + +const TEST_RUNS = 1_000_000 +const MAX_OPS_BATCH_SIZE = 35 +const KB = 1000 + +function runTestCase(testCase, documentSizeBytes) { + const initialText = 'A'.repeat(documentSizeBytes) + + console.log(`test: ${testCase.name}`) + console.log(`opsBatchSize\topsPerSeconds ${documentSizeBytes / 1000}KB`) + for (let i = 1; i <= MAX_OPS_BATCH_SIZE; i++) { + const ops = testCase(documentSizeBytes, i) + + let timeTotal = 0 + for (let i = 0; i < TEST_RUNS; i++) { + const start = performance.now() + try { + text.apply(initialText, ops) + } catch { + console.error(`test failed: ${testCase.name}, with ops:`) + console.error(ops) + return + } + const done = performance.now() + timeTotal += done - start + } + + const opsPerSeconds = TEST_RUNS / (timeTotal / 1000) + console.log(`${i}\t${opsPerSeconds}`) + } +} + +const randomAdditionTestCase = (docSize, opsSize) => + Array.from({ length: opsSize }, () => ({ + p: Math.floor(Math.random() * docSize), + i: 'B', + })) + +const sequentialAdditionsTestCase = (docSize, opsSize) => + Array.from({ length: opsSize }, (_, i) => ({ p: i + docSize, i: 'B' })) + +const sequentialAdditionsInMiddleTestCase = (docSize, opsSize) => + Array.from({ length: opsSize }, (_, i) => ({ + p: Math.floor(docSize / 2) + i, + i: 'B', + })) + +const randomDeletionTestCase = (docSize, opsSize) => + Array.from({ length: opsSize }, (_, i) => ({ + p: Math.floor(Math.random() * (docSize - 1 - i)), + d: 'A', + })) + +const sequentialDeletionTestCase = (docSize, opsSize) => + Array.from({ length: opsSize }, (_, i) => ({ + p: docSize - 1 - i, + d: 'A', + })) + +const sequentialDeletionInMiddleTestCase = (docSize, opsSize) => + Array.from({ length: opsSize }, (_, i) => ({ + p: Math.floor(docSize / 2), + d: 'A', + })) + +for (const docSize of [10 * KB, 100 * KB]) { + for (const testCase of [ + randomAdditionTestCase, + sequentialAdditionsTestCase, + sequentialAdditionsInMiddleTestCase, + randomDeletionTestCase, + sequentialDeletionTestCase, + sequentialDeletionInMiddleTestCase, + ]) { + runTestCase(testCase, docSize) + } +} diff --git a/services/document-updater/package.json b/services/document-updater/package.json index b31f82197c..751b9bc114 100644 --- a/services/document-updater/package.json +++ b/services/document-updater/package.json @@ -9,6 +9,7 @@ "test:acceptance": "npm run test:acceptance:_run -- --grep=$MOCHA_GREP", "test:unit:_run": "mocha --recursive --reporter spec $@ test/unit/js", "test:unit": "npm run test:unit:_run -- --grep=$MOCHA_GREP", + "benchmark:apply": "node benchmarks/apply", "nodemon": "node --watch $NODE_APP_OPTIONS app.js", "lint": "eslint --max-warnings 0 --format unix .", "format": "prettier --list-different $PWD/'**/*.js'",