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 781b53f5d6
commit 8121d5ce4a
7 changed files with 93 additions and 91 deletions

View File

@ -61,9 +61,12 @@ struct ParsedMessage {
CefString message; CefString message;
}; };
size_t GetByteLength(const CefString& value) {
return value.size() * sizeof(CefString::char_type);
}
size_t GetMessageSize(const CefString& response) { size_t GetMessageSize(const CefString& response) {
return sizeof(MessageHeader) + return sizeof(MessageHeader) + GetByteLength(response);
(response.size() * sizeof(CefString::char_type));
} }
void CopyResponseIntoMemory(void* memory, const CefString& response) { void CopyResponseIntoMemory(void* memory, const CefString& response) {
@ -126,7 +129,7 @@ CefRefPtr<CefProcessMessage> BuildMessage(size_t threshold,
int context_id, int context_id,
int request_id, int request_id,
const CefString& response) { const CefString& response) {
if (response.size() <= threshold) { if (GetByteLength(response) <= threshold) {
return BuildListMessage(message_name, context_id, request_id, response); return BuildListMessage(message_name, context_id, request_id, response);
} else { } else {
return BuildBinaryMessage(message_name, context_id, request_id, response); 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()); static_cast<const bv_utils::RendererMessage*>(region->Memory());
const auto message_size = const auto message_size =
std::max(region->Size(), sizeof(bv_utils::BrowserMessage)); std::max(region->Size(), sizeof(bv_utils::BrowserMessage));
const auto renderer_time = renderer_msg->start_time;
const auto duration = finish_time - renderer_time; std::vector<uint8_t> data(message_size);
const auto start_time = bv_utils::Now(); 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( auto builder = CefSharedProcessMessageBuilder::Create(
bv_utils::kTestSendSMRProcessMessage, message_size); bv_utils::kTestSendSMRProcessMessage, message_size);
const auto browser_msg = bv_utils::CopyDataIntoMemory(data, builder->Memory());
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;
frame->SendProcessMessage(PID_RENDERER, builder->Build()); frame->SendProcessMessage(PID_RENDERER, builder->Build());
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -35,12 +35,14 @@ TimePoint Now();
CefRefPtr<CefBinaryValue> CreateCefBinaryValue( CefRefPtr<CefBinaryValue> CreateCefBinaryValue(
const std::vector<uint8_t>& data); const std::vector<uint8_t>& data);
void CopyDataIntoMemory(const std::vector<uint8_t>& data, void* dst);
RendererMessage GetRendererMsgFromBinary( RendererMessage GetRendererMsgFromBinary(
const CefRefPtr<CefBinaryValue>& value); const CefRefPtr<CefBinaryValue>& value);
BrowserMessage GetBrowserMsgFromBinary(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 } // namespace bv_utils