Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/convex/pgbenchy/k6/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
summary.json
58 changes: 58 additions & 0 deletions examples/convex/pgbenchy/k6/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
.PHONY: tpcb tpcb-info

MAKEFLAGS += -j2

# Existing configuration
rate ?= 2
duration ?= 60
rand = $(shell bash -c 'echo $$RANDOM')
testrun ?= "random-run-$(rand)"

# TPC-B configuration
SCALE_FACTOR ?= 10
CONNS ?= 10
REQUESTS ?= 10
RAMPING_DURATION ?= 10
CONSECUTIVE_DURATION ?= 20
RAMPS_COUNT ?= 1

tpcb-info:
@echo "========================================="
@echo "TPC-B Benchmark Runner"
@echo "========================================="
@echo "Configuration:"
@echo " CONVEX_URL: $(CONVEX_URL)"
@echo " SCALE_FACTOR: $(SCALE_FACTOR)"
@echo " CONNS: $(CONNS)"
@echo " REQUESTS: $(REQUESTS)"
@echo " RAMPING_DURATION: $(RAMPING_DURATION)s"
@echo " CONSECUTIVE_DURATION: $(CONSECUTIVE_DURATION)s"
@echo " RAMPS_COUNT: $(RAMPS_COUNT)"
@echo " TEST_RUN: $(testrun)"
@echo "========================================="
@echo ""

tpcb: tpcb-info
@if [ -z "$(CONVEX_URL)" ]; then \
echo "Error: CONVEX_URL environment variable is not set"; \
echo "Please set it to your Convex deployment URL"; \
exit 1; \
fi
@./k6 run \
--out json=results_$(testrun).json \
-e CONVEX_URL="$(CONVEX_URL)" \
-e SCALE_FACTOR="$(SCALE_FACTOR)" \
-e CONNS="$(CONNS)" \
-e REQUESTS="$(REQUESTS)" \
-e RAMPING_DURATION="$(RAMPING_DURATION)" \
-e CONSECUTIVE_DURATION="$(CONSECUTIVE_DURATION)" \
-e RAMPS_COUNT="$(RAMPS_COUNT)" \
-e TEST_RUN="$(testrun)" \
-o 'prometheus=namespace=k6' \
tpcb-convex.js
@echo ""
@echo "========================================="
@echo "Benchmark complete!"
@echo "Results saved to: results_$(testrun).json"
@echo "Summary saved to: summary.json"
@echo "========================================="
99 changes: 99 additions & 0 deletions examples/convex/pgbenchy/k6/common.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// common.js - Shared configuration for k6 TPC-B benchmarks

/**
* Creates a ramping-vus scenario configuration
*
* @param {number} rampingDuration - Duration of each ramp stage in seconds
* @param {number} consecutiveDuration - Duration of the steady state in seconds
* @param {number} ramps - Number of ramp stages
* @param {number} conns - Target number of VUs (connections)
* @returns {object} k6 scenario configuration
*/
export function scenario(rampingDuration, consecutiveDuration, ramps, conns) {
const stages = []

// Build ramping stages
for (let i = 1; i <= ramps; i++) {
const targetVUs = Math.ceil((conns / ramps) * i)

// Ramp up stage
stages.push({
duration: `${rampingDuration}s`,
target: targetVUs,
})

// Steady state stage
stages.push({
duration: `${consecutiveDuration}s`,
target: targetVUs,
})
}

return {
executor: 'ramping-vus',
startVUs: 0,
stages: stages,
gracefulRampDown: '30s',
}
}

/**
* Alternative: constant arrival rate scenario
* Use this for strict TPS control
*/
export function constantRateScenario(targetTPS, duration, maxVUs) {
return {
executor: 'constant-arrival-rate',
rate: targetTPS,
timeUnit: '1s',
duration: `${duration}s`,
preAllocatedVUs: Math.ceil(maxVUs / 2),
maxVUs: maxVUs,
}
}

/**
* Trend stats to include in summary
*/
export const trends = [
'avg',
'min',
'med',
'max',
'p(90)',
'p(95)',
'p(99)',
'count',
]

/**
* Default thresholds for TPC-B style workloads
*/
export const defaultThresholds = {
failed_requests: ['rate<0.1'], // Less than 10% failure rate
tx_trend: ['p(95)<1000'], // 95th percentile under 1 second
http_req_duration: ['p(95)<1000'], // HTTP latency under 1 second
}

/**
* Strict thresholds for production-grade testing
*/
export const strictThresholds = {
failed_requests: ['rate<0.01'], // Less than 1% failure rate
tx_trend: ['p(95)<200'], // 95th percentile under 200ms
http_req_duration: ['p(95)<200'],
}

/**
* Return a random integer between the minimum (inclusive)
* and maximum (exclusive) values
* @param {number} min - The minimum value to return.
* @param {number} max - The maximum value you want to return.
* @return {number} The random number between the min and max.
*/
export function getRandomInt(min, max) {
min = Math.ceil(min)
max = Math.floor(max)
// The maximum is exclusive and the minimum is inclusive
return Math.floor(Math.random() * (max - min) + min)
}
79 changes: 79 additions & 0 deletions examples/convex/pgbenchy/k6/summary.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import http from 'k6/http'
import { textSummary } from 'https://jslib.k6.io/k6-summary/0.0.1/index.js'

/* Setting up the environment variables for the test run. */
const testrun = __ENV.TEST_RUN
const origin = __ENV.TEST_ORIGIN
const benchmark = __ENV.BENCHMARK_ID
const run = __ENV.RUN_ID
const token = __ENV.SUPABENCH_TOKEN
const supabench_uri = __ENV.SUPABENCH_URI
? __ENV.SUPABENCH_URI
: 'http://localhost:8090'

/**
* Handle summary implementation that additionally sends the data to the reports server.
*/
export function handleSummary(data) {
console.log('Preparing the end-of-test summary...')
const started = Date.now()

// Send the results to remote server
if (!run) {
const report = {
output: textSummary(data, { indent: ' ', enableColors: false }),
raw: data,
benchmark_id: benchmark,
name: testrun ? testrun : null,
status: 'success',
origin: origin,
started_at: `${started - 60 * 1000}`,
ended_at: `${
started + parseInt(data.state.testRunDurationMs) + 60 * 1000
}`,
}

const resp = http.post(
`${supabench_uri}/api/collections/runs/records`,
JSON.stringify(report),
{
headers: {
'Content-Type': 'application/json',
Authorization: `Admin ${token}`,
},
}
)
if (resp.status != 200) {
console.error('Could not send summary, got status ' + resp.status)
}
} else {
const report = {
output: textSummary(data, { indent: ' ', enableColors: false }),
raw: data,
status: 'success',
started_at: `${started - 120 * 1000}`,
ended_at: `${
started + parseInt(data.state.testRunDurationMs) + 15 * 1000
}`,
}

const resp = http.patch(
`${supabench_uri}/api/collections/runs/records/${run}`,
JSON.stringify(report),
{
headers: {
'Content-Type': 'application/json',
Authorization: `Admin ${token}`,
},
}
)
if (resp.status != 200) {
console.error('Could not send summary, got status ' + resp.status)
}
}

return {
stdout: textSummary(data, { indent: ' ', enableColors: true }), // Show the text summary to stdout...
'summary.json': JSON.stringify(data), // and a JSON with all the details...
}
}
Loading
Loading