Speed benchmark of locators

By xngo on June 23, 2008

Selenium locators are not all equals. Some locators are faster than others. Therefore, I took up the task to measure the speed of each Selenium locators. The speed test that I did is to measure the time that each locator took to fill up the 1st 50 input fields of the 500 inputs fields. From the results, ID locator is the fastest.

The Xpath locator is always faster in Firefox than in Internet Explorer because Internet Explorer doesn't have a native Xpath support. Therefore, Selenium is using ajaxslt library when it handles Xpath in Internet Explorer.

Results of the speed benchmark

SUMMARY: *firefox2 [5 tries]
=========================
                 ID Avg. =    805.2 ms   (id=idX)                      
               NAME Avg. =   2273.2 ms   (name=nameX)                  
       CSS_SELECTOR Avg. =   2974.2 ms   (css=input[name="nameX"])     
     RELATIVE_XPATH Avg. =    907.2 ms   (xpath=//input[@name='nameX'])
     ABSOLUTE_XPATH Avg. =    773.0 ms   (xpath=/html/body/input[X])   
 NAME_AS_IDENTIFIER Avg. =   2377.2 ms   (identifier=nameX)    
 
SUMMARY: *iexplore7 [5 tries]
=========================
                 ID Avg. =   2103.0 ms   (id=idX)                      
               NAME Avg. =  42913.8 ms   (name=nameX)                  
       CSS_SELECTOR Avg. =   5724.4 ms   (css=input[name="nameX"])     
     RELATIVE_XPATH Avg. =  59996.2 ms   (xpath=//input[@name='nameX'])
     ABSOLUTE_XPATH Avg. =  26494.0 ms   (xpath=/html/body/input[X])   
 NAME_AS_IDENTIFIER Avg. =  41917.8 ms   (identifier=nameX)     

Codes used to measure the speed of locators

Before you run the code below, you have to put SeleniumData.html in the root directory of your webserver. And in the code, you may have to change localhost to your correspondent host.

/**
 * Benchmark the speeed of different Selenium locators.
 * - Put SeleniumData.html in the root directory of your webserver
 * - You may have to change localhost to your correspondent host.
 * @Author: Xuan Ngo
 */
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
 
import java.util.Calendar;
import java.util.Formatter;
 
import com.thoughtworks.selenium.DefaultSelenium;
 
public class LocatorsBenchmark
{
 
  public static void main(String[] args) 
  {
    LocatorsBenchmark oLocatorsBenchmark = new LocatorsBenchmark();
 
    /**
     * Generate test data.
     * SeleniumData.html should be put in the root directory 
     *  of your web server.
     */
    final String sFilename = "SeleniumData.html";
    final int iMaxInputsFields = 500;
    oLocatorsBenchmark.generateData(sFilename, iMaxInputsFields);
 
    /*******************************
     * Benchmark process start here.
     *******************************/
    final int iMaxFillInput = 50;
    final int iTry = 5;
 
    long lId              = 0;
    long lName            = 0;
    long lRelativeXpath   = 0;
    long lAbsoluteXpath   = 0;
    long lNameAsIdentifier= 0;
    long lCssSelector     = 0;
 
    final String[] aBrowserTypes = {"*firefox", "*iexplore"};
    for(int j=0; j<aBrowserTypes.length; j++)
    {
      final String sBaseUrl = "http://localhost";
      final String sUrl = "http://localhost/SeleniumData.html";
      final String sBrowserType = aBrowserTypes[j];
      for(int i=0; i<iTry; i++)
      {
        System.out.println(sBrowserType+":  Try "+i);
        lId               += oLocatorsBenchmark.fillData(iMaxFillInput, LocatorsBenchmark.ID, sBaseUrl, sUrl, sBrowserType);
        lName             += oLocatorsBenchmark.fillData(iMaxFillInput, LocatorsBenchmark.NAME, sBaseUrl, sUrl, sBrowserType);
        lCssSelector      += oLocatorsBenchmark.fillData(iMaxFillInput, LocatorsBenchmark.CSS_SELECTOR, sBaseUrl, sUrl, sBrowserType);
        lRelativeXpath    += oLocatorsBenchmark.fillData(iMaxFillInput, LocatorsBenchmark.RELATIVE_XPATH, sBaseUrl, sUrl, sBrowserType);
        lAbsoluteXpath    += oLocatorsBenchmark.fillData(iMaxFillInput, LocatorsBenchmark.ABSOLUTE_XPATH, sBaseUrl, sUrl, sBrowserType);
        lNameAsIdentifier += oLocatorsBenchmark.fillData(iMaxFillInput, LocatorsBenchmark.NAME_AS_IDENTIFIER, sBaseUrl, sUrl, sBrowserType);
        System.out.println("===================================\n");
      }
      /*************************
       * Calculate average time.
       *************************/
      System.out.println("SUMMARY: "+sBrowserType+ "["+iTry+" tries]");
      System.out.println("=========================");
      System.out.println( (new Formatter()).format("%27s %11s %-32s", "ID Avg. = ", (double)lId/(double)iTry+" ms", "  (id=idX)") );
      System.out.println( (new Formatter()).format("%27s %11s %-32s", "NAME Avg. = ", (double)lName/(double)iTry+" ms", "  (name=nameX)") );
      System.out.println( (new Formatter()).format("%27s %11s %-32s", "CSS_SELECTOR Avg. = ", (double)lCssSelector/(double)iTry+" ms", "  (css=input[name=\"nameX\"])") );
      System.out.println( (new Formatter()).format("%27s %11s %-32s", "RELATIVE_XPATH Avg. = ", (double)lRelativeXpath/(double)iTry+" ms", "  (xpath=//input[@name='nameX'])") );
      System.out.println( (new Formatter()).format("%27s %11s %-32s", "ABSOLUTE_XPATH Avg. = ", (double)lAbsoluteXpath/(double)iTry+" ms", "  (xpath=/html/body/input[X])") );
      System.out.println( (new Formatter()).format("%27s %11s %-32s", "NAME_AS_IDENTIFIER Avg. = ", (double)lNameAsIdentifier/(double)iTry+" ms", "  (identifier=nameX)") );
    }
  }
 
  /**
   * Implementation of benchmark class. 
   */
  public static int ID                = 0;
  public static int NAME              = 1;
  public static int RELATIVE_XPATH    = 2;
  public static int ABSOLUTE_XPATH    = 3;
  public static int NAME_AS_IDENTIFIER= 4; // Use the value of @name as identifier.
  public static int CSS_SELECTOR      = 5;
 
  private String[] m_aLocatorType = new String[]{ "ID", 
                          "NAME", 
                          "RELATIVE_XPATH",
                          "ABSOLUTE_XPATH", 
                          "NAME_AS_IDENTIFIER",
                          "CSS_SELECTOR", 
                          };
 
  private void generateData(final String sFilename, final int iMax)
  {
    try
    {
      BufferedWriter out = new BufferedWriter(new FileWriter(sFilename));
      out.write("<html><head><title>Selenium benchmark data</title></head><body>");
      for(int i=0; i<iMax; i++)
      {
        out.write("<input type=\"text\" id=\"id"+i+"\" name=\"name"+i+"\"/> "+i+"<br />");
      }
      out.write("</body></html>");
      out.close();
    }
    catch(IOException e) 
    {
      System.out.println(e.getMessage()+":\n"+e.getStackTrace());
    }   
  }
 
  private final long fillData(final int iMax, final int iLocatorType, final String sBaseUrl, final String sUrl, final String sBrowserType)
  {
    /*********************
     * Open test web page.
     *********************/
    final String sServerHost = "localhost";
    final int iServerPort = 4444;
    DefaultSelenium oDefaultSelenium = new DefaultSelenium(sServerHost, iServerPort, sBrowserType, sBaseUrl);
 
    oDefaultSelenium.start();
//oDefaultSelenium.useXpathLibrary("javascript-xpath");
    oDefaultSelenium.open(sUrl);
 
    /**************************************
     * Time time took to fill input fields.
     **************************************/
    Calendar oStart = Calendar.getInstance();
    for(int i=0; i<iMax; i++)
    {
      if(iLocatorType==ID)
      {
        oDefaultSelenium.type("id=id"+i, i+""); // ID
      }
      else if(iLocatorType==NAME)
      {
        oDefaultSelenium.type("name=name"+i, i+""); // NAME
      }
      else if(iLocatorType==RELATIVE_XPATH)
      {
        oDefaultSelenium.type("xpath=//input[@name='name"+i+"']", i+""); // RELATIVE_XPATH
      }
      else if(iLocatorType==ABSOLUTE_XPATH)
      {
        oDefaultSelenium.type("xpath=/html/body/input["+(i+1)+"]", i+""); // ABSOLUTE_XPATH
      }     
      else if(iLocatorType==NAME_AS_IDENTIFIER)
      {
        oDefaultSelenium.type("identifier=name"+i, i+""); // NAME_AS_IDENTIFIER
      }
      else if(iLocatorType==CSS_SELECTOR)
      {
        oDefaultSelenium.type("css=input[name=\"name"+i+"\"]", i+""); // CSS_SELECTOR
      }     
      else
      {
        System.out.println("Unknown Locator type: "+iLocatorType);
      }
    }
    Calendar oEnd = Calendar.getInstance();
 
    // Uncomment below to pause the execution of intructions so that you can see the results.
//    try{ Thread.sleep(10000); } catch(Exception ex){System.out.println(ex.getMessage());}
 
    oDefaultSelenium.stop();
 
    /************************
     * Calculate statistics. 
     ***********************/
    long lTotalRuntime = oEnd.getTimeInMillis() - oStart.getTimeInMillis();
    long lRuntime = lTotalRuntime;
 
    long lRuntimeHrs = lRuntime/(1000*3600);
    lRuntime = lRuntime - (lRuntimeHrs*1000*3600);// Runtime remaining.
    long lRuntimeMin = (lRuntime)/(1000*60);
    lRuntime = lRuntime - (lRuntimeMin*1000*60);  // Runtime remaining.
    long lRuntimeSec = lRuntime/(1000);
    lRuntime = lRuntime - (lRuntimeSec*1000);     // Runtime remaining.
 
    System.out.println(this.m_aLocatorType[iLocatorType]+" => Time Elapsed("+lTotalRuntime+" ms): "+lRuntimeHrs+" hr(s)  "+lRuntimeMin+" min(s)  "+lRuntimeSec+" sec(s)  "+lRuntime+" ms");
    return lTotalRuntime;
  }
 
}

About the author

Xuan Ngo is the founder of OpenWritings.net. He currently lives in Montreal, Canada. He loves to write about programming and open source subjects.