Skip to content

Commit aacff1d

Browse files
committed
test: Refactor Existing k6 Tests to Measure Accurately
* Refactored existing tests to give us more accurate average readings Signed-off-by: Atanas Atanasov <a.v.atanasov98@gmail.com>
1 parent e7eb4c3 commit aacff1d

File tree

5 files changed

+48
-28
lines changed

5 files changed

+48
-28
lines changed

tools-and-tests/k6/average-load/bn-server-status.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ import {ServerStatusRequest} from "../lib/grpc.js";
66
// Configure k6 VUs scheduling and iterations & thresholds
77
export const options = {
88
stages: [
9-
{ duration: '2m', target: 40 }, // traffic ramp-up from 1 to 40 users (all CNs and a shadow MN) over 5 minutes.
10-
{ duration: '3m', target: 100 }, // stay at 100 users for 3 minutes
9+
{ duration: '1m', target: 40 }, // traffic ramp-up from 1 to 40 users (all CNs and a shadow MN) over 5 minutes.
10+
{ duration: '1m', target: 100 }, // stay at 100 users for 3 minutes
1111
{ duration: '1m', target: 0 }, // ramp-down to 0 users
1212
],
1313
thresholds: { // todo make these good defaults, we need these to display tags in the result, but also to ping us if they go over

tools-and-tests/k6/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tools-and-tests/k6/run-k6-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ run_server_status_test() {
7474

7575
run_query_validation_test() {
7676
run_bn
77-
run_simulator 0 10
77+
run_simulator 0 100
7878
echo "Running query validation test..."
7979
k6 run ./smoke/bn-query-validation.js >> "${k6_out_file}" 2>&1
8080
echo "Query validation test completed."

tools-and-tests/k6/smoke/bn-query-validation.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@ import {GetBlockRequest, ServerStatusRequest} from "../lib/grpc.js";
77
export const options = {
88
thresholds: { // todo make these good defaults, we need these to display tags in the result, but also to ping us if they go over
99
'grpc_req_duration{name:block_node_server_status}': ['p(95)<300'],
10-
'grpc_req_duration{name:get_first_block}': ['p(95)<300'],
11-
'grpc_req_duration{name:get_last_block}': ['p(95)<300'],
10+
'grpc_req_duration{name:get_block}': ['p(95)<300'],
1211
},
1312
};
1413

15-
1614
// load test configuration data
1715
const data = new SharedArray('BN Test Configs', function () {
1816
return JSON.parse(open('./../data.json')).configs;
@@ -26,7 +24,7 @@ client.load([data.protobufPath],
2624
'block-node/api/block_stream_subscribe_service.proto');
2725

2826
// run test
29-
export default () => {
27+
export default async () => {
3028
client.connect(data.blockNodeUrl, {
3129
plaintext: true
3230
});
@@ -44,24 +42,26 @@ export default () => {
4442
if (firstAvailableBlock === '18446744073709551615') {
4543
console.log(`No blocks to fetch, exiting test.`);
4644
} else {
47-
const getFirstBlockRequestParams = {
48-
tags: {name: 'get_first_block'},
49-
};
50-
const firstAvailableBlockResponse = new GetBlockRequest(client).invoke(firstAvailableBlock, getFirstBlockRequestParams);
51-
check(firstAvailableBlockResponse, {
52-
'block fetch status is OK': (r) => r && r.status === StatusOK,
53-
'fetched block number is correct': (r) => r && r.message.block.items[0].blockHeader.number === firstAvailableBlock,
54-
});
55-
console.log(`Fetched Block '${firstAvailableBlock}' with size '${firstAvailableBlockResponse.message.block.items.length}' items`);
56-
const getLastBlockRequestParams = {
57-
tags: {name: 'get_last_block'},
45+
for (let i = parseInt(firstAvailableBlock); i <= parseInt(lastAvailableBlock); i++) {
46+
const getBlockRequestParams = {
47+
tags: {name: 'get_block'},
48+
}
49+
const blockResponse = new GetBlockRequest(client).invoke(i, getBlockRequestParams);
50+
try {
51+
check(blockResponse, {
52+
'block fetch status is OK': (r) => r && r.status
53+
=== StatusOK,
54+
'fetched block number is correct': (r) => r && parseInt(
55+
r.message.block.items[0].blockHeader.number) === i,
56+
});
57+
} catch (e) {
58+
console.log(`error fetching block: ${i}\nresponse: ${JSON.stringify(blockResponse)}`)
59+
}
60+
// Sleep just for a tiny bit, it seems networking with k6 is not always fast enough and we do see
61+
// some errors when fetching blocks, sometimes no data is received at all.
62+
await new Promise(r => setTimeout(r, 50));
5863
}
59-
const lastAvailableBlockResponse = new GetBlockRequest(client).invoke(lastAvailableBlock, getLastBlockRequestParams);
60-
check(lastAvailableBlockResponse, {
61-
'block fetch status is OK': (r) => r && r.status === StatusOK,
62-
'fetched block number is correct': (r) => r && r.message.block.items[0].blockHeader.number === lastAvailableBlock,
63-
});
64-
console.log(`Fetched Block '${lastAvailableBlock}' with size '${lastAvailableBlockResponse.message.block.items.length}' items`);
64+
sleep(1)
6565
}
6666
client.close();
6767
sleep(1);

tools-and-tests/k6/smoke/bn-stream-validation.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Client, StatusOK, Stream } from 'k6/net/grpc';
22
import { check, sleep } from 'k6';
33
import { SharedArray } from 'k6/data';
44
import {ServerStatusRequest, SubscribeBlockStreamRequest} from "../lib/grpc.js";
5+
import {Trend} from "k6/metrics";
6+
import { instance } from 'k6/execution';
57

68
// setup options
79
export const options = {
@@ -23,6 +25,9 @@ client.load([data.protobufPath],
2325
'block-node/api/block_access_service.proto',
2426
'block-node/api/block_stream_subscribe_service.proto');
2527

28+
// this trend measures the reception of a full block along with its endOfBlock message
29+
const trend = new Trend('full_block_stream_duration', true);
30+
2631
// run test
2732
export default () => {
2833
client.connect(data.blockNodeUrl, {
@@ -59,12 +64,27 @@ export default () => {
5964
const subscribeParams = {
6065
tags: {name: 'subscribe_block_stream'}
6166
}
67+
const timingMap = new Map();
6268
const stream = new SubscribeBlockStreamRequest(client).invoke(subscribeParams);
6369
stream.on('data', (subscribeStreamResponse) => {
6470
if (subscribeStreamResponse.blockItems) {
65-
console.log(`Stream Response: BlockHeader for Block ${JSON.stringify(subscribeStreamResponse.blockItems.blockItems[0].blockHeader.number)}`);
71+
const receivedAt = instance.currentTestRunDuration;
72+
const header = subscribeStreamResponse.blockItems.blockItems[0].blockHeader;
73+
if (header) {
74+
// we want to put in the map only if a header is present because a block
75+
// could be sent in multiple chunks, we only care about the block received in full, starting from
76+
// the first chunk (must include header) to the endOfBlock message
77+
const bn = header.number;
78+
timingMap.set(parseInt(bn), receivedAt);
79+
console.log(`Stream Response: BlockHeader for Block ${JSON.stringify(bn)}`);
80+
}
6681
} else if (subscribeStreamResponse.endOfBlock) {
67-
console.log(`Stream Response: endOfBlock for Block ${JSON.stringify(subscribeStreamResponse.endOfBlock.blockNumber)}`);
82+
const receivedAt = instance.currentTestRunDuration;
83+
const bn = subscribeStreamResponse.endOfBlock.blockNumber;
84+
const startedAt = timingMap.get(parseInt(bn));
85+
trend.add(receivedAt - startedAt); // This should be accurate for more that millis (micros, nanos)
86+
timingMap.delete(parseInt(bn));
87+
console.log(`Stream Response: endOfBlock for Block ${JSON.stringify(bn)}`);
6888
} else {
6989
console.log(`Unknown Stream Response: , ${JSON.stringify(subscribeStreamResponse)}`);
7090
}

0 commit comments

Comments
 (0)