Update ipc_performance_test to compare similar transfers (see #3502)

This commit is contained in:
Nik Pavlov 2023-10-18 19:41:33 +00:00 committed by Marshall Greenblatt
parent e6a96e2bec
commit 15caa9858d
7 changed files with 93 additions and 91 deletions

View File

@ -61,9 +61,12 @@ struct ParsedMessage {
CefString message;
};
size_t GetByteLength(const CefString& value) {
return value.size() * sizeof(CefString::char_type);
}
size_t GetMessageSize(const CefString& response) {
return sizeof(MessageHeader) +
(response.size() * sizeof(CefString::char_type));
return sizeof(MessageHeader) + GetByteLength(response);
}
void CopyResponseIntoMemory(void* memory, const CefString& response) {
@ -126,7 +129,7 @@ CefRefPtr<CefProcessMessage> BuildMessage(size_t threshold,
int context_id,
int request_id,
const CefString& response) {
if (response.size() <= threshold) {
if (GetByteLength(response) <= threshold) {
return BuildListMessage(message_name, context_id, request_id, response);
} else {
return BuildBinaryMessage(message_name, context_id, request_id, response);

View File

@ -285,18 +285,18 @@ void OnTestSMRProcessMessageReceived(
static_cast<const bv_utils::RendererMessage*>(region->Memory());
const auto message_size =
std::max(region->Size(), sizeof(bv_utils::BrowserMessage));
const auto renderer_time = renderer_msg->start_time;
const auto duration = finish_time - renderer_time;
const auto start_time = bv_utils::Now();
std::vector<uint8_t> data(message_size);
const auto browser_msg =
reinterpret_cast<bv_utils::BrowserMessage*>(data.data());
browser_msg->test_id = renderer_msg->test_id;
browser_msg->duration = finish_time - renderer_msg->start_time;
browser_msg->start_time = bv_utils::Now();
auto builder = CefSharedProcessMessageBuilder::Create(
bv_utils::kTestSendSMRProcessMessage, message_size);
const auto browser_msg =
static_cast<bv_utils::BrowserMessage*>(builder->Memory());
browser_msg->test_id = renderer_msg->test_id;
browser_msg->duration = duration;
browser_msg->start_time = start_time;
bv_utils::CopyDataIntoMemory(data, builder->Memory());
frame->SendProcessMessage(PID_RENDERER, builder->Build());
}

View File

@ -207,15 +207,17 @@ class IpcDelegate final : public client::ClientAppRenderer::Delegate {
const auto buffer_size =
std::max(message_size, sizeof(bv_utils::RendererMessage));
const auto start_time = bv_utils::Now();
std::vector<uint8_t> buffer(buffer_size);
const auto renderer_msg =
reinterpret_cast<bv_utils::RendererMessage*>(buffer.data());
renderer_msg->test_id = test_id;
renderer_msg->start_time = bv_utils::Now();
auto builder = CefSharedProcessMessageBuilder::Create(
bv_utils::kTestSendSMRProcessMessage, buffer_size);
auto renderer_msg =
static_cast<bv_utils::RendererMessage*>(builder->Memory());
renderer_msg->test_id = test_id;
renderer_msg->start_time = start_time;
bv_utils::CopyDataIntoMemory(buffer, builder->Memory());
frame->SendProcessMessage(PID_BROWSER, builder->Build());
}
@ -229,8 +231,8 @@ class IpcDelegate final : public client::ClientAppRenderer::Delegate {
CefString code = "testSendProcessMessageResult(" +
std::to_string(msg.test_id) + ", " +
bv_utils::ToMilliString(rendered_to_browser) + ", " +
bv_utils::ToMilliString(browser_to_rendered) + ");";
bv_utils::ToMicroSecString(rendered_to_browser) + ", " +
bv_utils::ToMicroSecString(browser_to_rendered) + ");";
frame->ExecuteJavaScript(code, frame->GetURL(), 0);
}

View File

@ -1,8 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>IPC Performance Tests</title>
<script src="https://cdn.plot.ly/plotly-2.12.1.min.js"></script>
<script src="https://cdn.plot.ly/plotly-2.26.0.min.js"></script>
<style>
body {
font-family: Tahoma, Serif;
@ -70,8 +71,8 @@
<td>
<p>
There is no progress indication of the tests because it
significantly influences measurements. <br />It usually takes 30
seconds (for 100 samples) to complete the tests. <br /><b>AL</b> -
significantly influences measurements. <br />It usually takes 15
seconds (for 1000 samples) to complete the tests. <br /><b>AL</b> -
ArgumentList-based process messages. <b>SM</b> -
SharedMemoryRegion-based process messages.
</p>
@ -83,7 +84,7 @@
<input
id="sSamples"
type="text"
value="100"
value="1000"
required
pattern="[0-9]+"
/>
@ -97,8 +98,8 @@
<thead>
<tr>
<td class="center" style="width: 8%">Message Size</td>
<td class="center" style="width: 8%">AL Round Trip Avg,&nbsp;ms</td>
<td class="center" style="width: 8%">SM Round Trip Avg,&nbsp;ms</td>
<td class="center" style="width: 8%">AL Round Trip Avg,&nbsp;μs</td>
<td class="center" style="width: 8%">SM Round Trip Avg,&nbsp;μs</td>
<td class="center" style="width: 10%">Relative Trip Difference</td>
<td class="center" style="width: 8%">AL Speed,&nbsp;MB/s</td>
<td class="center" style="width: 8%">SM Speed,&nbsp;MB/s</td>
@ -126,27 +127,18 @@
let box_plot_test_data = [];
let round_trip_avg_plot_data = [];
function nextTest(test) {
setTimeout(() => {
execNextTest(test.index);
}, 0);
}
function testSendProcessMessageResult(
testIndex,
fromRendererToBrowser,
fromBrowserToRenderer
) {
const test = tests[testIndex];
const roundTrip = fromRendererToBrowser + fromBrowserToRenderer;
test.totalRoundTrip += roundTrip;
test.sample++;
box_plot_test_data[testIndex].x.push(roundTrip);
setTimeout(() => {
execTest(testIndex);
}, 10);
setTimeout(execTest, 0, testIndex);
}
function sendRequest(size, testIndex) {
@ -176,10 +168,10 @@
const test = tests[testIndex];
if (test.sample >= test.totalSamples) {
return nextTest(test);
setTimeout(execNextTest, 0, testIndex);
} else {
test.func(test.messageSize, test.index);
}
test.func(test.index);
}
function column(prepared, value) {
@ -269,8 +261,8 @@
((avgRoundTripSMR - avgRoundTrip) / avgRoundTrip) * 100;
// In MB/s
const speed = test.messageSize / (avgRoundTrip * 1000);
const speedSMR = testSMR.messageSize / (avgRoundTripSMR * 1000);
const speed = test.messageSize / avgRoundTrip;
const speedSMR = testSMR.messageSize / avgRoundTripSMR;
const relativeSpeedDiff = ((speedSMR - speed) / speed) * 100;
const stdDeviation = getStandardDeviation(
@ -362,16 +354,16 @@
function execNextTest(testIndex) {
testIndex++;
if (tests.length <= testIndex) {
return testSuiteFinished();
testSuiteFinished();
} else {
return execTest(testIndex);
execTest(testIndex);
}
}
function execQueuedTests(totalSamples) {
prepareQueuedTests(totalSamples);
// Let the updated table render before starting the tests
setTimeout(() => execNextTest(-1), 200);
setTimeout(execNextTest, 200, -1);
}
function setSettingsState(disabled) {
@ -401,7 +393,6 @@
function humanFileSize(bytes) {
const step = 1024;
const originalBytes = bytes;
if (Math.abs(bytes) < step) {
return bytes + " B";
@ -432,17 +423,12 @@
};
for (let size = 512; size <= 512 * 1024; size = size * 2) {
queueTest(humanFileSize(size) + " AL", size, (testIndex) =>
sendRequest(size, testIndex)
);
queueTest(humanFileSize(size) + " SM", size, (testIndex) =>
sendSMRRequest(size, testIndex)
);
queueTest(humanFileSize(size) + " AL", size, sendRequest);
queueTest(humanFileSize(size) + " SM", size, sendSMRRequest);
}
const totalSamples = parseInt(document.getElementById("sSamples").value);
prepareQueuedTests(totalSamples);
</script>
</body>
</html>
</html>

View File

@ -7,26 +7,24 @@
namespace {
constexpr int kSingleQueryErrorCode = 5;
constexpr size_t kMessageSizeThreshold = 16000;
constexpr size_t kMsgSizeThresholdInBytes = 16000;
constexpr auto kCharSize = sizeof(CefString::char_type);
enum class TestType { SUCCESS, FAILURE };
CefString GenerateResponse(size_t size, char ch) {
return CefString(std::string(size, ch));
CefString GenerateResponse(size_t count, char ch) {
return std::string(count, ch);
}
CefString GenerateResponse(size_t size, wchar_t ch) {
return CefString(std::wstring(size, ch));
CefString GenerateResponse(size_t count, wchar_t ch) {
return std::wstring(count, ch);
}
template <class CharType>
class ThresholdTestHandler final : public SingleLoadTestHandler {
public:
ThresholdTestHandler(TestType type, size_t message_size, CharType symbol)
: test_type_(type),
message_size_(message_size),
message_size_str_(std::to_string(message_size)),
symbol_(symbol) {}
ThresholdTestHandler(TestType type, size_t string_length, CharType symbol)
: test_type_(type), string_length_(string_length), symbol_(symbol) {}
std::string GetMainHTML() override {
const std::string& errorCodeStr = std::to_string(kSingleQueryErrorCode);
@ -35,7 +33,8 @@ class ThresholdTestHandler final : public SingleLoadTestHandler {
"<html><body><script>\n"
// Send the query.
"var request_id = window." +
std::string(kJSQueryFunc) + "({\n request: '" + message_size_str_ +
std::string(kJSQueryFunc) + "({\n request: '" +
std::to_string(string_length_) +
"',\n persistent: false,\n"
" onSuccess: function(response) {\n"
" window.mrtNotify(response);\n"
@ -63,7 +62,7 @@ class ThresholdTestHandler final : public SingleLoadTestHandler {
EXPECT_FALSE(got_notify_);
got_notify_.yes();
auto expected = GenerateResponse(message_size_, symbol_);
auto expected = GenerateResponse(string_length_, symbol_);
switch (test_type_) {
case TestType::SUCCESS:
@ -108,7 +107,7 @@ class ThresholdTestHandler final : public SingleLoadTestHandler {
AssertMainFrame(frame);
EXPECT_NE(0, query_id);
EXPECT_FALSE(persistent);
EXPECT_EQ(message_size_str_, request.ToString());
EXPECT_EQ(std::to_string(string_length_), request.ToString());
const size_t message_size =
static_cast<size_t>(std::stoi(request.ToString()));
@ -130,8 +129,7 @@ class ThresholdTestHandler final : public SingleLoadTestHandler {
private:
const TestType test_type_;
const size_t message_size_;
const std::string message_size_str_;
const size_t string_length_;
const CharType symbol_;
CefRefPtr<Callback> callback_;
@ -149,20 +147,22 @@ using WCharTestHandlerPtr = CefRefPtr<WCharTestHandler>;
} // namespace
TEST(MessageRouterTest, ThresholdMessageUnderSuccessCallback) {
const auto UnderThreshold = kMessageSizeThreshold - 1;
const auto under_threshold = kMsgSizeThresholdInBytes - kCharSize;
const auto string_length = under_threshold / kCharSize;
CharTestHandlerPtr handler =
new CharTestHandler(TestType::SUCCESS, UnderThreshold, 'A');
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
new CharTestHandler(TestType::SUCCESS, string_length, 'A');
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
TEST(MessageRouterTest, ThresholMessageExactdSuccessCallback) {
TEST(MessageRouterTest, ThresholdMessageExactSuccessCallback) {
const auto string_length = kMsgSizeThresholdInBytes / kCharSize;
CharTestHandlerPtr handler =
new CharTestHandler(TestType::SUCCESS, kMessageSizeThreshold, 'A');
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
new CharTestHandler(TestType::SUCCESS, string_length, 'A');
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();
@ -170,10 +170,11 @@ TEST(MessageRouterTest, ThresholMessageExactdSuccessCallback) {
}
TEST(MessageRouterTest, ThresholdMessageOverSuccessCallback) {
const auto OverThreshold = kMessageSizeThreshold + 1;
const auto over_threshold = kMsgSizeThresholdInBytes + kCharSize;
const auto string_length = over_threshold / kCharSize;
CharTestHandlerPtr handler =
new CharTestHandler(TestType::SUCCESS, OverThreshold, 'A');
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
new CharTestHandler(TestType::SUCCESS, string_length, 'A');
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();
@ -181,21 +182,23 @@ TEST(MessageRouterTest, ThresholdMessageOverSuccessCallback) {
}
TEST(MessageRouterTest, ThresholdMessageUnderFailureCallback) {
const auto UnderThreshold = kMessageSizeThreshold - 1;
const auto under_threshold = kMsgSizeThresholdInBytes - kCharSize;
const auto string_length = under_threshold / kCharSize;
CharTestHandlerPtr handler =
new CharTestHandler(TestType::FAILURE, UnderThreshold, 'A');
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
new CharTestHandler(TestType::FAILURE, string_length, 'A');
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
TEST(MessageRouterTest, ThresholMessageOverdFailureCallback) {
const auto OverThreshold = kMessageSizeThreshold + 1;
TEST(MessageRouterTest, ThresholdMessageOverFailureCallback) {
const auto over_threshold = kMsgSizeThresholdInBytes + kCharSize;
const auto string_length = over_threshold / kCharSize;
CharTestHandlerPtr handler =
new CharTestHandler(TestType::FAILURE, OverThreshold, 'A');
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
new CharTestHandler(TestType::FAILURE, string_length, 'A');
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();
@ -203,10 +206,11 @@ TEST(MessageRouterTest, ThresholMessageOverdFailureCallback) {
}
TEST(MessageRouterTest, ThresholdUtf8MessageUnderSuccessCallback) {
const auto UnderThreshold = kMessageSizeThreshold - 1;
const auto under_threshold = kMsgSizeThresholdInBytes - kCharSize;
const auto string_length = under_threshold / kCharSize;
WCharTestHandlerPtr handler =
new WCharTestHandler(TestType::SUCCESS, UnderThreshold, L'\u304B');
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
new WCharTestHandler(TestType::SUCCESS, string_length, L'\u304B');
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();
@ -214,10 +218,11 @@ TEST(MessageRouterTest, ThresholdUtf8MessageUnderSuccessCallback) {
}
TEST(MessageRouterTest, ThresholdUtf8MessageOverSuccessCallback) {
const auto OverThreshold = kMessageSizeThreshold + 1;
const auto over_threshold = kMsgSizeThresholdInBytes + kCharSize;
const auto string_length = over_threshold / kCharSize;
WCharTestHandlerPtr handler =
new WCharTestHandler(TestType::SUCCESS, OverThreshold, L'\u304B');
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
new WCharTestHandler(TestType::SUCCESS, string_length, L'\u304B');
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();

View File

@ -18,6 +18,10 @@ CefRefPtr<CefBinaryValue> CreateCefBinaryValue(
return CefBinaryValue::Create(data.data(), data.size());
}
void CopyDataIntoMemory(const std::vector<uint8_t>& data, void* dst) {
memcpy(dst, data.data(), data.size());
}
RendererMessage GetRendererMsgFromBinary(
const CefRefPtr<CefBinaryValue>& value) {
DCHECK_GE(value->GetSize(), sizeof(RendererMessage));
@ -33,9 +37,9 @@ BrowserMessage GetBrowserMsgFromBinary(const CefRefPtr<CefBinaryValue>& value) {
return *reinterpret_cast<const BrowserMessage*>(data.data());
}
std::string ToMilliString(const Duration& duration) {
std::string ToMicroSecString(const Duration& duration) {
const auto ms =
std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(
duration);
return std::to_string(ms.count());

View File

@ -35,12 +35,14 @@ TimePoint Now();
CefRefPtr<CefBinaryValue> CreateCefBinaryValue(
const std::vector<uint8_t>& data);
void CopyDataIntoMemory(const std::vector<uint8_t>& data, void* dst);
RendererMessage GetRendererMsgFromBinary(
const CefRefPtr<CefBinaryValue>& value);
BrowserMessage GetBrowserMsgFromBinary(const CefRefPtr<CefBinaryValue>& value);
std::string ToMilliString(const Duration& duration);
std::string ToMicroSecString(const Duration& duration);
} // namespace bv_utils