Measuring GUI performance

Last edited on

Overview

Instrumentation by Squish can have an effect on the GUI performance of an application. For example, clicking a button to open a dialog may take 10ms when run without Squish, and 20ms or more when run with Squish.

This is important to keep in mind when measuring time required for certain operations in your application.

Simple time measuring

A very simple implementation for measuring time of some operations could look like this (Python):

import os
import os.path
import sys
import time

def main():
    startApplication('"' + os.environ["SQUISH_PREFIX"] + "/examples/qt/addressbook/addressbook" + '"')

    mouseClick(waitForObject({"text": "New", "type": "QToolButton", "visible": "1"}))

    # Get Add button reference before measuring time
    # to avoid measuring this unrelated object look up
    # as well
    add_button = waitForObject({"text": "Add", "type": "QToolButton", "visible": "1"})

    start_time = time.time()

    # MEASURED CODE - START
    mouseClick(add_button)
    waitForObject({"type": "Dialog", "visible": "1"})
    # MEASURED CODE - END

    t = time.time() - start_time

    msg = "Time required for showing Add dialog: Expected max.: %.4f, Actual: %.4f"

    # Unrealistically low value to demonstrate a
    # fail (actually requires 0.04 to 0.1 seconds
    # to show the dialog on some computers)
    expected = 0.001
    msg2 = msg % (expected, t)
    my_verify(t < expected, msg2)

    # Realistic value to demonstrate a pass
    expected = 0.2
    msg3 = msg % (expected, t)
    my_verify(t < expected, msg3)

def my_verify(condition, message):
    if condition:
        test.passes(message)
    else:
        test.fail(message)
test.py

Simple time measuring with calculation of average time required

Performing the desired operation n number of times and calculating the average time required can be useful to ensure that an operation more consistently performs as desired, not just once. (Although this should probably also include checking for values which cause a fail, regardless of the average. The example below does not do this however.)

Here is a simple implementation which calculates and checks the average time instead (Python):

import os
import os.path
import sys
import time

def main():
    startApplication('"' + os.environ["SQUISH_PREFIX"] + "/examples/qt/addressbook/addressbook" + '"')

    # Try the operation n number of times
    n = 10.0
    sum = 0.0
    for i in range(n):
        sum += measure_add_dlg_open()
    average = sum / n

    msg = "Time required for showing Add dialog: Expected max.: %.4f, Actual: %.4f"

    # Unrealistically low value to demonstrate a
    # fail (actually requires 0.04 to 0.1 seconds
    # to show the dialog on some computers)
    expected = 0.001
    msg2 = msg % (expected, average)
    my_verify(average < expected, msg2)

    # Realistic value to demonstrate a pass
    expected = 0.2
    msg3 = msg % (expected, average)
    my_verify(average < expected, msg3)

def measure_add_dlg_open():
    mouseClick(waitForObject({"text": "New", "type": "QToolButton", "visible": "1"}))

    # Get Add button reference before measuring time
    # to avoid measuring this unrelated object look up
    # as well
    add_button = waitForObject({"text": "Add", "type": "QToolButton", "visible": "1"})

    start_time = time.time()

    # MEASURED CODE - START
    mouseClick(add_button)
    waitForObject({"type": "Dialog", "visible": "1"})
    # MEASURED CODE - END

    t = time.time() - start_time

    # Close dialog
    sendEvent("QCloseEvent", waitForObject({"type": "Dialog", "visible": "1"}))

    return t

def my_verify(condition, message):
    if condition:
        test.passes(message)
    else:
        test.fail(message)
test.py

Measuring absolute time required for executing n number of times

Another example (Python):

import os
import os.path
import sys
import time

def main():
    startApplication('"' + os.environ["SQUISH_PREFIX"] + "/examples/qt/addressbook/addressbook" + '"')

    mouseClick(waitForObject({"text": "New", "type": "QToolButton", "visible": "1"}))
    n = 50.0
    sum = measure_add_dlg_open(n)

    msg = "Time required for showing and closing Add dialog %d times: Expected max.: %.3f, Actual: %.3f"

    # Unrealistically low value to demonstrate a
    # fail
    expected = 0.1
    msg2 = msg % (n, expected, sum)
    my_verify(sum < expected, msg2)

    # Realistic value to demonstrate a pass
    expected = 20
    msg3 = msg % (n, expected, sum)
    my_verify(sum < expected, msg3)

def measure_add_dlg_open(n):
    # Get Add button reference before measuring time
    # to avoid measuring this unrelated object look up
    # as well
    add_button = waitForObject({"text": "Add", "type": "QToolButton", "visible": "1"})

    start_time = time.time()

    # MEASURED CODE - START
    measure_add_dlg_open_2(n, add_button)
    # MEASURED CODE - END

    t = time.time() - start_time
    return t

def measure_add_dlg_open_2(n, add_button):
    for i in range(n):
        mouseClick(add_button)
        dlg = waitForObject({"type": "Dialog", "visible": "1"})
        sendEvent("QCloseEvent", dlg)

def my_verify(condition, message):
    if condition:
        test.passes(message)
    else:
        test.fail(message)
test.py