From 7c4f371ce2a2c1ad0023e20991ae0919b4eacdcb Mon Sep 17 00:00:00 2001 From: Alka Trivedi Date: Tue, 21 Jan 2025 17:00:33 +0530 Subject: [PATCH] refactor --- .../system-test-multiplexed-session.cfg | 2 +- .kokoro/system-test.sh | 6 - .kokoro/trampoline_v2.sh | 1 + benchmark/benchmarking-multiplexed-session.js | 110 ++++++++++++++++++ owlbot.py | 2 +- test/spanner.ts | 1 - 6 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 benchmark/benchmarking-multiplexed-session.js diff --git a/.kokoro/presubmit/node14/system-test-multiplexed-session.cfg b/.kokoro/presubmit/node14/system-test-multiplexed-session.cfg index 8bf1160cd..aeeace4e8 100644 --- a/.kokoro/presubmit/node14/system-test-multiplexed-session.cfg +++ b/.kokoro/presubmit/node14/system-test-multiplexed-session.cfg @@ -12,6 +12,6 @@ env_vars: { } env_vars: { - key: "GOOGLE_CLOUD_SPANNER_ENABLE_MULTIPLEXED_SESSIONS" + key: "GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS" value: "true" } \ No newline at end of file diff --git a/.kokoro/system-test.sh b/.kokoro/system-test.sh index bb20a4220..a90d5cfec 100755 --- a/.kokoro/system-test.sh +++ b/.kokoro/system-test.sh @@ -45,12 +45,6 @@ if [[ $KOKORO_BUILD_ARTIFACTS_SUBDIR = *"continuous"* ]] || [[ $KOKORO_BUILD_ART trap cleanup EXIT HUP fi -# If tests are running with enabled multiplexed session, configure env -# GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS -if [[ $GOOGLE_CLOUD_SPANNER_ENABLE_MULTIPLEXED_SESSIONS = *"true"* ]]; then - export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=true -fi - npm run system-test # codecov combines coverage across integration and unit tests. Include diff --git a/.kokoro/trampoline_v2.sh b/.kokoro/trampoline_v2.sh index 5d6cfcca5..23b5f7893 100755 --- a/.kokoro/trampoline_v2.sh +++ b/.kokoro/trampoline_v2.sh @@ -165,6 +165,7 @@ if [[ -n "${KOKORO_BUILD_ID:-}" ]]; then # For flakybot "KOKORO_GITHUB_COMMIT_URL" "KOKORO_GITHUB_PULL_REQUEST_URL" + "GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS" ) elif [[ "${TRAVIS:-}" == "true" ]]; then RUNNING_IN_CI="true" diff --git a/benchmark/benchmarking-multiplexed-session.js b/benchmark/benchmarking-multiplexed-session.js new file mode 100644 index 000000000..fce411e5f --- /dev/null +++ b/benchmark/benchmarking-multiplexed-session.js @@ -0,0 +1,110 @@ +/*! + * Copyright 2025 Google LLC. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const muxEnabledTrue = []; +const muxEnabledFalse = []; +const transaction_times = []; +async function main( + instanceId, + databaseId, + projectId, + multiplexedEnabled, + numThreads, + numQueries +) { + async function readQuery(database) { + const startTime = Date.now(); + const query = { + sql: 'SELECT * FROM Singers', + }; + await database.run(query); + const operationTime = Date.now() - startTime; + transaction_times.push(operationTime); + } + + async function runQueries() { + multiplexedEnabled === 'true' + ? (process.env.GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS = true) + : (process.env.GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS = false); + + const startTime = Date.now(); + const {Spanner} = require('../build/src'); + const spanner = new Spanner({ + projectId, + }); + + // Gets a reference to a Cloud Spanner instance and database + const instance = spanner.instance(instanceId); + const database = instance.database(databaseId); + + for (let i = 0; i < numQueries; i++) { + await readQuery(database); + } + + multiplexedEnabled === 'true' + ? muxEnabledTrue.push(Date.now() - startTime) + : muxEnabledFalse.push(Date.now() - startTime); + } + + function calculatePercentiles(latencies) { + // Step 1: Sort the array + const sortedLatencies = latencies.slice().sort((a, b) => a - b); + + // Step 2: Calculate p50 (50th percentile) + const p50Index = Math.floor(0.5 * sortedLatencies.length); + const p50Latency = sortedLatencies[p50Index]; + + // Step 3: Calculate p90 (90th percentile) + const p90Index = Math.floor(0.9 * sortedLatencies.length); + const p90Latency = sortedLatencies[p90Index]; + // Step 3: Calculate p99 (99th percentile) + const p99Index = Math.floor(0.99 * sortedLatencies.length); + const p99Latency = sortedLatencies[p99Index]; + + return { + p50: p50Latency, + p90: p90Latency, + p99: p99Latency, + }; + } + + async function runConcurrently() { + const promises = []; + for (let i = 0; i < numThreads; i++) { + promises.push(runQueries()); + } + await Promise.all(promises); + } + + runConcurrently() + .then(() => { + const percentiles = calculatePercentiles(transaction_times); + console.log(`p50 Latency: ${percentiles.p50}`); + console.log(`p90 Latency: ${percentiles.p90}`); + console.log(`p99 Latency: ${percentiles.p99}`); + }) + .catch(error => { + console.log('error: ', error); + }); +} + +process.on('unhandledRejection', err => { + console.error(err.message); + process.exitCode = 1; +}); +main(...process.argv.slice(2)); diff --git a/owlbot.py b/owlbot.py index cf7c6d663..2a9b067a1 100644 --- a/owlbot.py +++ b/owlbot.py @@ -64,7 +64,7 @@ common_templates = gcp.CommonTemplates() templates = common_templates.node_library(source_location='build/src') -s.copy(templates, excludes=[".kokoro/samples-test.sh",".github/release-trigger.yml"]) +s.copy(templates, excludes=[".kokoro/samples-test.sh", ".kokoro/trampoline_v2.sh", ".github/release-trigger.yml"]) node.postprocess_gapic_library_hermetic() diff --git a/test/spanner.ts b/test/spanner.ts index ec2398c9b..3dfb7cead 100644 --- a/test/spanner.ts +++ b/test/spanner.ts @@ -68,7 +68,6 @@ import TypeCode = google.spanner.v1.TypeCode; import NullValue = google.protobuf.NullValue; import {SessionFactory} from '../src/session-factory'; import {MultiplexedSession} from '../src/multiplexed-session'; -import {BatchTransaction} from '../src/batch-transaction'; const { AlwaysOnSampler,