Skip to content

Commit

Permalink
Merge pull request #111 from MohamedSabthar/load-test-improve
Browse files Browse the repository at this point in the history
Improve serdes load test by separating client code from service
  • Loading branch information
MohamedSabthar authored Nov 29, 2022
2 parents 66b99b9 + 9c9859e commit 66c22ac
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 101 deletions.
Binary file modified load-tests/proto3_test/scripts/load_test.jar
Binary file not shown.
76 changes: 49 additions & 27 deletions load-tests/proto3_test/scripts/load_test/client.bal
Original file line number Diff line number Diff line change
Expand Up @@ -17,50 +17,72 @@
import ballerina/io;
import ballerina/http;
import ballerina/time;
import ballerina/lang.runtime;
import ballerina/serdes;

type User record {
readonly int id;
string name;
int age;
};

const time:Seconds EXECUTION_TIME = 3600;

public function main(string label, string outputCsvPath) returns error? {
http:Client loadTestClient = check new ("http://bal.perf.test", retryConfig = {count: 3, interval: 3});
http:Client loadTestClient = check new ("http://bal.perf.test", httpVersion = http:HTTP_1_1);

boolean result = check loadTestClient->get("/serdes/start");
if result {
io:println("Client started communication");
} else {
io:println("Could not start communication: client creation failed in serdes service");
}
serdes:Proto3Schema serdes = check new (User);
User user = {id: 0, name: "default", age: 0};
byte[] encodedPayload = check serdes.serialize(user);
byte[] defaultPayload = encodedPayload;

map<string> testResults = {};
time:Utc startedTime = time:utcNow();
time:Utc expiryTime = time:utcAddSeconds(startedTime, EXECUTION_TIME);
io:println("Communication started");

boolean finished = false;
while !finished {
map<string>?|error res = loadTestClient->get("/serdes/result");
if res is error {
io:println("Error occured", res);
} else if res is map<string> {
finished = true;
testResults = res;
} else {
io:println("waiting for result...");
time:Utc timer = time:utcNow();
int sampleCount = 0;
while time:utcDiffSeconds(expiryTime, time:utcNow()) > 0d {
do {
byte[] encodedResponse = check loadTestClient->post("/serdes/next", encodedPayload);
if encodedResponse.length() > 0 {
encodedPayload = encodedResponse;
} else {
encodedPayload = defaultPayload;
}
sampleCount += 1;
if isOneMinutePassed(timer) {
user = check serdes.deserialize(encodedPayload);
io:println("User: ", user);
timer = time:utcNow();
}
} on fail error e {
io:println(e);
}
runtime:sleep(60);
}
int errorCount = check int:fromString(testResults.get("errorCount"));
decimal time = check decimal:fromString(testResults.get("time"));
int sentCount = check int:fromString(testResults.get("sentCount"));
int receivedCount = check int:fromString(testResults.get("receivedCount"));

time:Utc endedTime = time:utcNow();
time:Seconds timeElasped = time:utcDiffSeconds(endedTime, startedTime);
io:println("Communication ended: ", {
"Started time": startedTime,
"Ended time": endedTime,
"Total time elasped": timeElasped
});

map<int> testResults = check loadTestClient->get("/serdes/result");

int errorCount = testResults.get("errorCount");
int operationCount = testResults.get("operationCount");
any[] results = [
label, sentCount, <float>time / <float>receivedCount,
0, 0, 0, 0, 0, 0, <float>errorCount / <float>sentCount,
<float>receivedCount / <float>time, 0, 0, time:utcNow()[0], 0, 1];
label, sampleCount, <float>timeElasped / <float>operationCount,
0, 0, 0, 0, 0, 0, <float>errorCount / <float>sampleCount,
<float>operationCount / <float>timeElasped, 0, 0, time:utcNow()[0], 0, 1];
check writeResultsToCsv(results, outputCsvPath);
}

function isOneMinutePassed(time:Utc timer) returns boolean {
return time:utcDiffSeconds(time:utcNow(), timer) > 60d;
}

function writeResultsToCsv(any[] results, string outputPath) returns error? {
string[] finalResult = [];
foreach var result in results {
Expand Down
92 changes: 18 additions & 74 deletions load-tests/proto3_test/src/server.bal
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,12 @@
import ballerina/serdes;
import ballerina/io;
import ballerina/http;
import ballerina/time;
import ballerina/log;

configurable int PORT = 9100;
const time:Seconds EXECUTION_TIME = 3600;

time:Utc startedTime = time:utcNow();
time:Utc endedTime = time:utcNow();

isolated int errorCount = 0;
isolated int serializationCount = 0;
isolated int deserializationCount = 0;

boolean completed = false;

type User record {
readonly int id;
string name;
Expand All @@ -40,49 +31,33 @@ type User record {

table<User> key(id) users = table [];

service /serdes on new http:Listener(PORT) {
service /serdes on new http:Listener(9100, httpVersion = http:HTTP_1_1) {

function init() returns error? {
check loadUserTable();
}

resource function get 'start() returns boolean {
http:Client|error clientEP = new (string `http://localhost:${PORT}/serdes`);
if clientEP is error {
return false;
}
resetCountersAndTime();
_ = start beginCommunication(clientEP);
return true;
}

resource function post next(http:Request request) returns byte[]|error {
serdes:Proto3Schema serdes = check new (User);
byte[] encodedPayload = check request.getBinaryPayload();
User nextUser = handleDeserialization(serdes, encodedPayload);
User|error user = handleDeserialization(serdes, encodedPayload);
User nextUser = user is User ? users.get((user.id + 1) % (users.length() - 1)) : users.get(0);
return handleSerialization(serdes, nextUser);
}

resource function get result() returns map<string>? {
if completed {
string errCount = "";
string sentCount = "";
string receivedCount = "";
string time = time:utcDiffSeconds(endedTime, startedTime).toString();

lock {
errCount = errorCount.toBalString();
}
lock {
sentCount = serializationCount.toString();
}
lock {
receivedCount = deserializationCount.toString();
}

return {errorCount: errCount, time, sentCount, receivedCount};
resource function get result() returns map<int> {
map<int> result = {};
lock {
result["errorCount"] = errorCount;
}
lock {
result["operationCount"] = serializationCount;
}
return ();
lock {
result["operationCount"] = result.get("operationCount") + deserializationCount;
}
resetCounters();
return result;
}
}

Expand All @@ -96,33 +71,7 @@ function loadUserTable() returns error? {
log:printInfo("User table loaded.");
}

function beginCommunication(http:Client clientEP) returns error? {
log:printInfo("Communication started");
completed = false;
final int totalUsers = users.length();
User user = users.get(0);

time:Utc expiryTime = time:utcAddSeconds(startedTime, EXECUTION_TIME);
while time:utcDiffSeconds(expiryTime, time:utcNow()) > 0d {
serdes:Proto3Schema serdes = check new (User);
byte[] encodedPayload = handleSerialization(serdes, user);
byte[] encodedResponse = check clientEP->post("/next", encodedPayload);
User response = handleDeserialization(serdes, encodedResponse);
user = users.get((response.id + 1) % (totalUsers - 1));
}

completed = true;
endedTime = time:utcNow();

log:printInfo("Communication ended",
keyValue = {
"Started time": startedTime,
"Ended time": endedTime,
"Total time elasped": time:utcDiffSeconds(endedTime, startedTime)
});
}

function resetCountersAndTime() {
function resetCounters() {
lock {
errorCount = 0;
}
Expand All @@ -132,9 +81,6 @@ function resetCountersAndTime() {
lock {
deserializationCount = 0;
}

startedTime = time:utcNow();
endedTime = time:utcNow();
}

function handleSerialization(serdes:Schema serdes, User user) returns byte[] {
Expand All @@ -154,9 +100,8 @@ function handleSerialization(serdes:Schema serdes, User user) returns byte[] {
return response;
}

function handleDeserialization(serdes:Schema serdes, byte[] payload) returns User {
function handleDeserialization(serdes:Schema serdes, byte[] payload) returns User|error {
User|serdes:Error user = serdes.deserialize(payload);
User nextUser = users.get(0);
if user is serdes:Error {
log:printError("Deserialization faild: ", user);
lock {
Expand All @@ -166,7 +111,6 @@ function handleDeserialization(serdes:Schema serdes, byte[] payload) returns Use
lock {
deserializationCount += 1;
}
nextUser = users.get((user.id + 1) % (users.length() - 1));
}
return nextUser;
return user;
}

0 comments on commit 66c22ac

Please sign in to comment.