BiDi Protocol in Selenium 4 - not just network and console logs!
Previously, we showed how to record network requests and console logs in Selenium 4 via the currently-in-draft BiDirectional (or BiDi) protocol, but that was far from the only new capability that the new BiDi-related APIs provide! In this article we’ll show how to use Selenium 4 to inspect browser performance and resource-utilization metrics, using examples written in Scala.
Collecting Browser Performance and Resource Utilization data in Selenium 3
In previous versions of Selenium, there were no dedicated APIs for retrieving performance-related information from the browser - making it difficult to obtain performance data from the browser session while running your tests. You could open the DevTools while the browser was still open, but that approach breaks down if you want to automate metric collection and/or collect metrics periodically.
Performance Metrics and Memory Profiling in Selenium 4
To demonstrate the new APIs for browser performance introduced in Selenium 4, we’ll use Scala with Selenium’s Java library.
BiDi support in action
To start, we instantiate our WebDriver
and create a buffer to hold performance metric information:
|
|
In the above block, we’re launching Chrome and opening a connection to it using the CDP (in a future release Selenium will use the BiDi protocol).
To pull and store performance metrics, we first need to enable metrics collection. Then we’ll create a collectMetrics
method for pulling
the metrics from the browser and storing them in our metricsByTimestamp
buffer.
|
|
devTools.send(Performance.getMetrics)
sends a request to the browser for performance metrics, returning a list of Metric
objects that in our case are
added to the metricsByTimestamp
buffer.
Optional
parameter of Performance.enable
is for setting the ‘Time domain’ that the browser should use when collecting performance metrics. Further
information on this parameter can be found in the CDP documentation.
In addition to performance metrics, memory profiling can be enabled with just the following:
|
|
Pulling the sampling information can be done with devTools.send(Memory.getAllTimeSamplingProfile)
, which we’ll use later on.
Optional
parameters of Memory.startSampling
are for controlling the sampling interval and whether to randomize intervals between samples. Further
information on these parameters can be found in the CDP documentation.
Putting together all the earlier code snippets, you can test against any website you’d like and print out the collected performance information with the following code:
|
|
If you run the above code you should see the collected metrics printed out from before and after the page was loaded (list of metrics abridged for brevity):
1638229293144:
Documents -> 2
Nodes -> 8
JSHeapUsedSize -> 983432
JSHeapTotalSize -> 2043904
...
1638229295705:
Documents -> 37
Nodes -> 2824
JSHeapUsedSize -> 3024696
JSHeapTotalSize -> 4808704
...
Followed by the heap allocation information printed out afterwards (abridged for brevity):
Size of heap allocation: 128 bytes
Total bytes attributed to this sample: 131072 bytes
Size of heap allocation: 896 bytes
Total bytes attributed to this sample: 131072 bytes
...
Potential Applications
A more practical application for using this information than printing to console would be to compare the resource utilization of your web application over time. This could be done by saving the metrics to a storage solution such as AWS S3, or streaming the data into a solution such as AWS Kinesis for further processing/aggregation before storage.
Comparing the stored metrics with the latest run could be used to identify potential memory leaks or other performance regressions in your application.
Limitations
Like the other BiDi-related APIs in Selenium 4, the browser support for these new APIs is unfortunately limited to a subset of browsers - currently only Chrome and Microsoft Edge support them.
Additionally, while these APIs are supposed to use the BiDi protocol, they currently use the Chrome DevTools Protocol because the BiDi protocol is still in a draft state.
Lastly, while collecting performance information can be useful as part of testing with Selenium, the authors of the library themselves discourage using it for performance testing. That’s not to say the data isn’t worth collecting, but it is likely insufficient on its own to reliably identify broader performance issues (responsiveness, latency, etc.).
Conclusion
The new performance-related APIs in Selenium 4 can provide testers more information on their application in the browser than previous versions, but the currently limited browser support may hamper its utility for larger organizations.