mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	CefSharedProcessMessageBuilder supports creation of a CefProcessMessage backed by a CefSharedMemoryRegion. Performance tests comparing the existing ArgumentList approach and the new SharedMemoryRegion approach have been added to cefclient at http://tests/ipc_performance. CefMessageRouter has been updated to use SharedMemoryRegion as transport for larger message payloads. The threshold is configurable via |CefMessageRouterConfig.message_size_threshold|. To test: run `ceftests --gtest_filter=SendSharedProcessMessageTest.*:SharedProcessMessageTest.*:MessageRouterTest.Threshold*`
		
			
				
	
	
		
			448 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
			
		
		
	
	
			448 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			HTML
		
	
	
	
	
	
<!DOCTYPE html>
 | 
						|
<html>
 | 
						|
  <head>
 | 
						|
    <title>IPC Performance Tests</title>
 | 
						|
    <script src="https://cdn.plot.ly/plotly-2.12.1.min.js"></script>
 | 
						|
    <style>
 | 
						|
      body {
 | 
						|
        font-family: Tahoma, Serif;
 | 
						|
        font-size: 10pt;
 | 
						|
      }
 | 
						|
 | 
						|
      .left {
 | 
						|
        text-align: left;
 | 
						|
      }
 | 
						|
 | 
						|
      .right {
 | 
						|
        text-align: right;
 | 
						|
      }
 | 
						|
 | 
						|
      .positive {
 | 
						|
        color: green;
 | 
						|
        font-weight: bold;
 | 
						|
      }
 | 
						|
 | 
						|
      .negative {
 | 
						|
        color: red;
 | 
						|
        font-weight: bold;
 | 
						|
      }
 | 
						|
 | 
						|
      .center {
 | 
						|
        text-align: center;
 | 
						|
      }
 | 
						|
 | 
						|
      table.resultTable {
 | 
						|
        border: 1px solid black;
 | 
						|
        border-collapse: collapse;
 | 
						|
        empty-cells: show;
 | 
						|
        width: 100%;
 | 
						|
      }
 | 
						|
 | 
						|
      table.resultTable td {
 | 
						|
        padding: 2px 4px;
 | 
						|
        border: 1px solid black;
 | 
						|
      }
 | 
						|
 | 
						|
      table.resultTable > thead > tr {
 | 
						|
        font-weight: bold;
 | 
						|
        background: lightblue;
 | 
						|
      }
 | 
						|
 | 
						|
      table.resultTable > tbody > tr:nth-child(odd) {
 | 
						|
        background: white;
 | 
						|
      }
 | 
						|
 | 
						|
      table.resultTable > tbody > tr:nth-child(even) {
 | 
						|
        background: lightgray;
 | 
						|
      }
 | 
						|
 | 
						|
      .hide {
 | 
						|
        display: none;
 | 
						|
      }
 | 
						|
    </style>
 | 
						|
  </head>
 | 
						|
 | 
						|
  <body background-color="white">
 | 
						|
    <h1>IPC Performance Tests</h1>
 | 
						|
 | 
						|
    <table>
 | 
						|
      <tr>
 | 
						|
        <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> -
 | 
						|
            ArgumentList-based process messages. <b>SM</b> -
 | 
						|
            SharedMemoryRegion-based process messages.
 | 
						|
          </p>
 | 
						|
        </td>
 | 
						|
      </tr>
 | 
						|
      <tr>
 | 
						|
        <td>
 | 
						|
          Samples:
 | 
						|
          <input
 | 
						|
            id="sSamples"
 | 
						|
            type="text"
 | 
						|
            value="100"
 | 
						|
            required
 | 
						|
            pattern="[0-9]+"
 | 
						|
          />
 | 
						|
          <button id="sRun" autofocus onclick="runTestSuite()">Run</button>
 | 
						|
        </td>
 | 
						|
      </tr>
 | 
						|
    </table>
 | 
						|
 | 
						|
    <div style="padding-top: 10px; padding-bottom: 10px">
 | 
						|
      <table id="resultTable" class="resultTable">
 | 
						|
        <thead>
 | 
						|
          <tr>
 | 
						|
            <td class="center" style="width: 8%">Message Size</td>
 | 
						|
            <td class="center" style="width: 8%">AL Round Trip Avg, ms</td>
 | 
						|
            <td class="center" style="width: 8%">SM Round Trip Avg, ms</td>
 | 
						|
            <td class="center" style="width: 10%">Relative Trip Difference</td>
 | 
						|
            <td class="center" style="width: 8%">AL Speed, MB/s</td>
 | 
						|
            <td class="center" style="width: 8%">SM Speed, MB/s</td>
 | 
						|
            <td class="center" style="width: 10%">Relative Speed Difference</td>
 | 
						|
            <td class="center" style="width: 8%">AL Standard Deviation</td>
 | 
						|
            <td class="center" style="width: 8%">SM Standard Deviation</td>
 | 
						|
          </tr>
 | 
						|
        </thead>
 | 
						|
        <tbody>
 | 
						|
          <!-- result rows here -->
 | 
						|
        </tbody>
 | 
						|
      </table>
 | 
						|
    </div>
 | 
						|
 | 
						|
    <div id="round_trip_avg_chart">
 | 
						|
      <!-- Average round trip linear chart will be drawn inside this DIV -->
 | 
						|
    </div>
 | 
						|
 | 
						|
    <div id="box_plot_chart">
 | 
						|
      <!-- Box plot of round trip time will be drawn inside this DIV -->
 | 
						|
    </div>
 | 
						|
 | 
						|
    <script type="text/javascript">
 | 
						|
      let tests = [];
 | 
						|
      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);
 | 
						|
      }
 | 
						|
 | 
						|
      function sendRequest(size, testIndex) {
 | 
						|
        window.testSendProcessMessage({
 | 
						|
          size: size,
 | 
						|
          testId: testIndex,
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      function sendSMRRequest(size, testIndex) {
 | 
						|
        window.testSendSMRProcessMessage({
 | 
						|
          size: size,
 | 
						|
          testId: testIndex,
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      function getStandardDeviation(array, mean) {
 | 
						|
        const n = array.length;
 | 
						|
        if (n < 5) return null;
 | 
						|
        return Math.sqrt(
 | 
						|
          array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) /
 | 
						|
            (n - 1)
 | 
						|
        );
 | 
						|
      }
 | 
						|
 | 
						|
      function execTest(testIndex) {
 | 
						|
        const test = tests[testIndex];
 | 
						|
 | 
						|
        if (test.sample >= test.totalSamples) {
 | 
						|
          return nextTest(test);
 | 
						|
        }
 | 
						|
 | 
						|
        test.func(test.index);
 | 
						|
      }
 | 
						|
 | 
						|
      function column(prepared, value) {
 | 
						|
        return (
 | 
						|
          "<td class='right'>" + (!prepared ? "-" : value.toFixed(2)) + "</td>"
 | 
						|
        );
 | 
						|
      }
 | 
						|
 | 
						|
      function relativeDiffColumn(prepared, value, isBiggerBetter) {
 | 
						|
        if (!prepared) return "<td class='right'>-</td>";
 | 
						|
 | 
						|
        const isPositive = value > 0 == isBiggerBetter;
 | 
						|
        return [
 | 
						|
          "<td class='right ",
 | 
						|
          isPositive ? "positive" : "negative",
 | 
						|
          "'>",
 | 
						|
          value > 0 ? "+" : "",
 | 
						|
          value.toFixed(2),
 | 
						|
          "%</td>",
 | 
						|
        ].join("");
 | 
						|
      }
 | 
						|
 | 
						|
      function displayResult(test) {
 | 
						|
        const id = "testResultRow_" + test.index;
 | 
						|
 | 
						|
        const markup = [
 | 
						|
          "<tr id='",
 | 
						|
          id,
 | 
						|
          "'>",
 | 
						|
          "<td class='left'>",
 | 
						|
          test.name,
 | 
						|
          "</td>",
 | 
						|
          column(test.prepared, test.avgRoundTrip),
 | 
						|
          column(test.prepared, test.avgRoundTripSMR),
 | 
						|
          relativeDiffColumn(test.prepared, test.relativeTripDiff, false),
 | 
						|
          column(test.prepared, test.speed),
 | 
						|
          column(test.prepared, test.speedSMR),
 | 
						|
          relativeDiffColumn(test.prepared, test.relativeSpeedDiff, true),
 | 
						|
          "<td class='right'>",
 | 
						|
          !test.prepared || test.stdDeviation == null
 | 
						|
            ? "-"
 | 
						|
            : test.stdDeviation.toFixed(2),
 | 
						|
          "</td>",
 | 
						|
          "<td class='right'>",
 | 
						|
          !test.prepared || test.stdDeviationSMR == null
 | 
						|
            ? "-"
 | 
						|
            : test.stdDeviationSMR.toFixed(2),
 | 
						|
          "</td>",
 | 
						|
          "</tr>",
 | 
						|
        ].join("");
 | 
						|
 | 
						|
        const row = document.getElementById(id);
 | 
						|
        if (row) {
 | 
						|
          row.outerHTML = markup;
 | 
						|
        } else {
 | 
						|
          const tbody = document.getElementById("resultTable").tBodies[0];
 | 
						|
          tbody.insertAdjacentHTML("beforeEnd", markup);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      function buildTestResults(tests) {
 | 
						|
        testResults = [];
 | 
						|
 | 
						|
        let oldRoundTrip = {
 | 
						|
          x: [],
 | 
						|
          y: [],
 | 
						|
          type: "scatter",
 | 
						|
          name: "ArgumentList",
 | 
						|
        };
 | 
						|
 | 
						|
        let newRoundTrip = {
 | 
						|
          x: [],
 | 
						|
          y: [],
 | 
						|
          type: "scatter",
 | 
						|
          name: "SharedMemoryRegion",
 | 
						|
        };
 | 
						|
 | 
						|
        for (let i = 0; i < tests.length / 2; i++) {
 | 
						|
          const index = testResults.length;
 | 
						|
 | 
						|
          const test = tests[i * 2];
 | 
						|
          const testSMR = tests[i * 2 + 1];
 | 
						|
 | 
						|
          const avgRoundTrip = test.totalRoundTrip / test.totalSamples;
 | 
						|
          const avgRoundTripSMR = testSMR.totalRoundTrip / testSMR.totalSamples;
 | 
						|
          const relativeTripDiff =
 | 
						|
            ((avgRoundTripSMR - avgRoundTrip) / avgRoundTrip) * 100;
 | 
						|
 | 
						|
          // In MB/s
 | 
						|
          const speed = test.messageSize / (avgRoundTrip * 1000);
 | 
						|
          const speedSMR = testSMR.messageSize / (avgRoundTripSMR * 1000);
 | 
						|
          const relativeSpeedDiff = ((speedSMR - speed) / speed) * 100;
 | 
						|
 | 
						|
          const stdDeviation = getStandardDeviation(
 | 
						|
            box_plot_test_data[test.index].x,
 | 
						|
            avgRoundTrip
 | 
						|
          );
 | 
						|
          const stdDeviationSMR = getStandardDeviation(
 | 
						|
            box_plot_test_data[testSMR.index].x,
 | 
						|
            avgRoundTripSMR
 | 
						|
          );
 | 
						|
 | 
						|
          testResults.push({
 | 
						|
            name: humanFileSize(test.messageSize),
 | 
						|
            index: index,
 | 
						|
            prepared: true,
 | 
						|
            avgRoundTrip: avgRoundTrip,
 | 
						|
            avgRoundTripSMR: avgRoundTripSMR,
 | 
						|
            relativeTripDiff: relativeTripDiff,
 | 
						|
            speed: speed,
 | 
						|
            speedSMR: speedSMR,
 | 
						|
            relativeSpeedDiff: relativeSpeedDiff,
 | 
						|
            stdDeviation: stdDeviation,
 | 
						|
            stdDeviationSMR: stdDeviationSMR,
 | 
						|
          });
 | 
						|
 | 
						|
          oldRoundTrip.x.push(test.messageSize);
 | 
						|
          newRoundTrip.x.push(test.messageSize);
 | 
						|
          oldRoundTrip.y.push(avgRoundTrip);
 | 
						|
          newRoundTrip.y.push(avgRoundTripSMR);
 | 
						|
        }
 | 
						|
 | 
						|
        round_trip_avg_plot_data = [oldRoundTrip, newRoundTrip];
 | 
						|
        return testResults;
 | 
						|
      }
 | 
						|
 | 
						|
      function buildEmptyTestResults(tests) {
 | 
						|
        testResults = [];
 | 
						|
        for (let i = 0; i < tests.length / 2; i++) {
 | 
						|
          const index = testResults.length;
 | 
						|
          const test = tests[i * 2];
 | 
						|
 | 
						|
          testResults.push({
 | 
						|
            name: humanFileSize(test.messageSize),
 | 
						|
            index: index,
 | 
						|
            prepared: false,
 | 
						|
          });
 | 
						|
        }
 | 
						|
        return testResults;
 | 
						|
      }
 | 
						|
 | 
						|
      function prepareQueuedTests(totalSamples) {
 | 
						|
        if (totalSamples <= 0) totalSamples = 1;
 | 
						|
 | 
						|
        tests.forEach((test) => {
 | 
						|
          test.sample = 0;
 | 
						|
          test.totalRoundTrip = 0;
 | 
						|
          test.totalSamples = totalSamples;
 | 
						|
        });
 | 
						|
 | 
						|
        testResults = buildEmptyTestResults(tests);
 | 
						|
        testResults.forEach((result) => displayResult(result));
 | 
						|
 | 
						|
        round_trip_avg_plot_data = [];
 | 
						|
        box_plot_test_data.forEach((data) => {
 | 
						|
          data.x = [];
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      function queueTest(name, messageSize, testFunc) {
 | 
						|
        const testIndex = tests.length;
 | 
						|
        test = {
 | 
						|
          name: name,
 | 
						|
          messageSize: messageSize,
 | 
						|
          index: testIndex,
 | 
						|
          func: testFunc,
 | 
						|
        };
 | 
						|
        tests.push(test);
 | 
						|
 | 
						|
        box_plot_test_data.push({
 | 
						|
          x: [],
 | 
						|
          type: "box",
 | 
						|
          boxpoints: "all",
 | 
						|
          name: name,
 | 
						|
          jitter: 0.3,
 | 
						|
          pointpos: -1.8,
 | 
						|
        });
 | 
						|
      }
 | 
						|
 | 
						|
      function execNextTest(testIndex) {
 | 
						|
        testIndex++;
 | 
						|
        if (tests.length <= testIndex) {
 | 
						|
          return testSuiteFinished();
 | 
						|
        } else {
 | 
						|
          return execTest(testIndex);
 | 
						|
        }
 | 
						|
      }
 | 
						|
 | 
						|
      function execQueuedTests(totalSamples) {
 | 
						|
        prepareQueuedTests(totalSamples);
 | 
						|
        // Let the updated table render before starting the tests
 | 
						|
        setTimeout(() => execNextTest(-1), 200);
 | 
						|
      }
 | 
						|
 | 
						|
      function setSettingsState(disabled) {
 | 
						|
        document.getElementById("sSamples").disabled = disabled;
 | 
						|
        document.getElementById("sRun").disabled = disabled;
 | 
						|
      }
 | 
						|
 | 
						|
      function testSuiteFinished() {
 | 
						|
        testResults = buildTestResults(tests);
 | 
						|
        testResults.forEach((result) => displayResult(result));
 | 
						|
 | 
						|
        const round_trip_layout = {
 | 
						|
          title: "Average round trip, ms (Smaller Better)",
 | 
						|
        };
 | 
						|
        Plotly.newPlot(
 | 
						|
          "round_trip_avg_chart",
 | 
						|
          round_trip_avg_plot_data,
 | 
						|
          round_trip_layout
 | 
						|
        );
 | 
						|
 | 
						|
        const box_plot_layout = {
 | 
						|
          title: "Round Trip Time, ms",
 | 
						|
        };
 | 
						|
        Plotly.newPlot("box_plot_chart", box_plot_test_data, box_plot_layout);
 | 
						|
        setSettingsState(false);
 | 
						|
      }
 | 
						|
 | 
						|
      function humanFileSize(bytes) {
 | 
						|
        const step = 1024;
 | 
						|
        const originalBytes = bytes;
 | 
						|
 | 
						|
        if (Math.abs(bytes) < step) {
 | 
						|
          return bytes + " B";
 | 
						|
        }
 | 
						|
 | 
						|
        const units = [" KB", " MB", " GB"];
 | 
						|
        let u = -1;
 | 
						|
        let count = 0;
 | 
						|
 | 
						|
        do {
 | 
						|
          bytes /= step;
 | 
						|
          u += 1;
 | 
						|
          count += 1;
 | 
						|
        } while (Math.abs(bytes) >= step && u < units.length - 1);
 | 
						|
 | 
						|
        return bytes.toString() + units[u];
 | 
						|
      }
 | 
						|
 | 
						|
      window.runTestSuite = () => {
 | 
						|
        Plotly.purge("round_trip_avg_chart");
 | 
						|
        Plotly.purge("box_plot_chart");
 | 
						|
        setSettingsState(true);
 | 
						|
        const totalSamples = parseInt(
 | 
						|
          document.getElementById("sSamples").value
 | 
						|
        );
 | 
						|
        execQueuedTests(totalSamples);
 | 
						|
        return false;
 | 
						|
      };
 | 
						|
 | 
						|
      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)
 | 
						|
        );
 | 
						|
      }
 | 
						|
 | 
						|
      const totalSamples = parseInt(document.getElementById("sSamples").value);
 | 
						|
      prepareQueuedTests(totalSamples);
 | 
						|
    </script>
 | 
						|
  </body>
 | 
						|
</html> |