As the network was down today I did some experimenting with a couple of
idioms we see in our tree to see which one is most efficient and by how
much.

These tests were run on Windows with optimized build, P III 500 MHZ, 512
MB RAM that was currently compiling Mozilla.

Test 1:

We have a loop calling a function that takes const nsAReadableString
&aStr as a parameter. Compare NS_ConvertASCIItoUCS2 performance against
NS_LITERAL_STRING performance, with short and long strings.

Typical run:

Short string
    convert:    46000
    literal:    16000
    =================
    Diff:       30000, literal 34.782609 of convert
Long string
    convert:   469000
    literal:    15000
    =================
    Diff:      454000, literal 3.198294 of convert

NOTE: On 50% of the runs the times for literal were 0.

NOTE: Typically we have short strings, we might in fact never have
strings that are so long that they require allocation in our code base.

Test 2:

We have a loop assigning a string (short and long) to an nsAutoString.
Compare AssignWithConversion() against Assign(NS_LITERAL_STRING()).

Typical run:

Short string
    convert:    62000
    literal:   141000
    =================
    Diff:      -79000, literal 227.419355 of convert
Long string
    convert:   390000
    literal:   469000
    =================
    Diff:      -79000, literal 120.256410 of convert

NOTE: Occasionally the literal string performed better with long
strings, best I saw was 88% of convert.

NOTE: Typically we have short strings, we might in fact never have
strings that are so long that they require allocation in our code base.

Conclusions:

It would pay off to convert (at least performance critical) function
calls to use NS_LITERAL_STRING instead of NS_ConvertASCIItoUCS2. Note
that on many cases this would require changing the function signature,
and maybe implementation, as well (you currently can not use
NS_LITERAL_STRING if the function parameter is nsString). Those cases
would require additional measurements to make sure that we do not slow
down the code.

Quick search with LXR shows that the following top level directories are
using NS_ConvertASCIItoUCS2 the most: editor, extensions, xpinstall,
content, dom, gfx, layout and webshell.

Caveat: NS_LITERAL_STRING expands to NS_ConvertASCIItoUCS2 on platforms
that do not support L"string".

Prefer AssignWithConversion() over Assign(NS_LITERAL_STRING()). I have
not checked why this happens, and feel bad about this. The results
surprised me.

Attachments include the test programs.

-- 
    Heikki Toivonen


-- 
   Heikki Toivonen
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 */

#include "nsString.h"

void foo (const nsAReadableString &aStr)
{
  aStr.Length();
}

int main (int argc, char* argv[]) 
{
  PRUint32 i=0;
  PRUint32 count = 100000;

  // short string, no allocation

  PRTime start1 = PR_Now();

  for ( ; i < count; i++) {
    foo(NS_ConvertASCIItoUCS2("123"));
  }

  PRTime end1 = PR_Now();

  i = 0;

  PRTime start2 = PR_Now();

  for ( ; i < count; i++) {
    foo(NS_LITERAL_STRING("123"));
  }

  PRTime end2 = PR_Now();

  // long string (150), allocation

  i = 0;

  PRTime start3 = PR_Now();

  for ( ; i < count; i++) {
    foo(NS_ConvertASCIItoUCS2("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
  }

  PRTime end3 = PR_Now();

  i = 0;

  PRTime start4 = PR_Now();

  for ( ; i < count; i++) {
    foo(NS_LITERAL_STRING(    "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
  }

  PRTime end4 = PR_Now();

  PRUint32 dur1 = end1 - start1;
  PRUint32 dur2 = end2 - start2;
  PRUint32 dur3 = end3 - start3;
  PRUint32 dur4 = end4 - start4;

  printf("Short string\n");
  printf("  convert: %8d\n",dur1);
  printf("  literal: %8d\n",dur2);
  printf("  =================\n");
  printf("  Diff:    %8d, literal %4lf of convert\n",dur1 - dur2, double(dur2)/double(dur1)*100);
  printf("Long string\n");
  printf("  convert: %8d\n",dur3);
  printf("  literal: %8d\n",dur4);
  printf("  =================\n");
  printf("  Diff:    %8d, literal %4lf of convert\n",dur3 - dur4, double(dur4)/double(dur3)*100);

  return 0;
}

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 */

#include "nsString.h"

int main (int argc, char* argv[]) 
{
  PRUint32 i=0;
  PRUint32 count = 100000;

  // short string, no allocation

  PRTime start1 = PR_Now();

  for ( ; i < count; i++) {
    nsAutoString foo;
    foo.AssignWithConversion("123");
  }

  PRTime end1 = PR_Now();

  i = 0;

  PRTime start2 = PR_Now();

  for ( ; i < count; i++) {
    nsAutoString foo;
    foo.Assign(NS_LITERAL_STRING("123"));
  }

  PRTime end2 = PR_Now();

  // long string (150), allocation

  i = 0;

  PRTime start3 = PR_Now();

  for ( ; i < count; i++) {
    nsAutoString foo;
    foo.AssignWithConversion(    "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
  }

  PRTime end3 = PR_Now();

  i = 0;

  PRTime start4 = PR_Now();

  for ( ; i < count; i++) {
    nsAutoString foo;
    foo.Assign(NS_LITERAL_STRING("123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"));
  }

  PRTime end4 = PR_Now();

  PRUint32 dur1 = end1 - start1;
  PRUint32 dur2 = end2 - start2;
  PRUint32 dur3 = end3 - start3;
  PRUint32 dur4 = end4 - start4;

  printf("Short string\n");
  printf("  convert: %8d\n",dur1);
  printf("  literal: %8d\n",dur2);
  printf("  =================\n");
  printf("  Diff:    %8d, literal %4lf of convert\n",dur1 - dur2, double(dur2)/double(dur1)*100);
  printf("Long string\n");
  printf("  convert: %8d\n",dur3);
  printf("  literal: %8d\n",dur4);
  printf("  =================\n");
  printf("  Diff:    %8d, literal %4lf of convert\n",dur3 - dur4, double(dur4)/double(dur3)*100);

  return 0;
}

Reply via email to