summaryrefslogtreecommitdiff
path: root/jstests/serverless/shard_split_performance_test.js
blob: 2633d804dec40c2fca384facf10fe6988eddc548 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
 *
 * Runs a number of shard split and moveChunk to compare the time it takes for both operations.
 * @tags: [requires_fcv_52, featureFlagShardSplit]
 */

load("jstests/serverless/libs/basic_serverless_test.js");
load("jstests/replsets/rslib.js");

const kBlockStart = "Entering 'blocking' state.";
const kReconfig = "Applying the split config";
const kWaitForRecipients = "Waiting for recipient to accept the split.";
const kEndMsg = "Shard split decision reached";
const kMoveChunkLog = "ctx\":\"MoveChunk\",\"msg\":\"Exiting commit critical section";

function runOneMoveChunk() {
    'use strict';

    load("jstests/sharding/libs/find_chunks_util.js");

    var st = new ShardingTest({mongos: 1, shards: 2});
    var kDbName = 'db';

    var mongos = st.s0;
    var shard0 = st.shard0.shardName;
    var shard1 = st.shard1.shardName;

    assert.commandWorked(mongos.adminCommand({enableSharding: kDbName}));
    st.ensurePrimaryShard(kDbName, shard0);

    const keyDoc = {a: 1};
    var ns = kDbName + '.foo';

    // Fail if find is not a valid shard key.
    assert.commandWorked(mongos.adminCommand({shardCollection: ns, key: keyDoc}));

    var chunkId = findChunksUtil.findOneChunkByNs(mongos.getDB('config'), ns, {shard: shard0})._id;

    assert.commandWorked(mongos.adminCommand({moveChunk: ns, find: keyDoc, to: shard1}));
    assert.eq(shard1, mongos.getDB('config').chunks.findOne({_id: chunkId}).shard);

    const moveMsg = checkLog.getLogMessage(st.shard0, kMoveChunkLog);
    assert(moveMsg);

    const moveJson = JSON.parse(moveMsg);
    const duration = parseInt(moveJson.attr.durationMillis, 10);

    mongos.getDB(kDbName).foo.drop();

    st.stop();

    jsTestLog(`moveChunk critical section lasted ${duration} ms`);

    return duration;
}

function extractTs(message) {
    assert(message);
    const msgJson = JSON.parse(message);
    return Date.parse(msgJson.t["$date"]);
}

function runOneSplit() {
    "use strict";

    const recipientTagName = "recipientNode";
    const recipientSetName = "recipientSetName";
    const test =
        new BasicServerlessTest({recipientTagName, recipientSetName, quickGarbageCollection: true});

    test.addRecipientNodes();
    test.donor.awaitSecondaryNodes();

    const primary = test.donor.getPrimary();

    const tenantIds = ["tenant1", "tenant2"];
    const operation = test.createSplitOperation(tenantIds);
    assert.commandWorked(operation.commit());

    test.removeRecipientNodesFromDonor();
    assertMigrationState(test.donor.getPrimary(), operation.migrationId, "committed");

    const blockTS = extractTs(checkLog.getLogMessage(primary, kBlockStart));
    const reconfigTS = extractTs(checkLog.getLogMessage(primary, kReconfig));
    const waitForRecipientsTS = extractTs(checkLog.getLogMessage(primary, kWaitForRecipients));
    const endTS = extractTs(checkLog.getLogMessage(primary, kEndMsg));

    const blockDurationMs = endTS - blockTS;
    const waitForRecipientsDurationMs = endTS - waitForRecipientsTS;
    const reconfigDurationMs = endTS - reconfigTS;

    const splitResult = {blockDurationMs, reconfigDurationMs, waitForRecipientsDurationMs};

    jsTestLog(`Performance result of shard split: ${tojson(splitResult)}`);
    const maximumReconfigDuration = 500;
    assert.lt(reconfigDurationMs,
              maximumReconfigDuration,
              `The reconfig critical section of split must be below ${maximumReconfigDuration}ms`);

    test.stop();
}

runOneMoveChunk();
runOneSplit();