Sane methods of checking which strings start with a (constant) string are slow in chrome code

RESOLVED WORKSFORME

Status

()

RESOLVED WORKSFORME
7 years ago
4 years ago

People

(Reporter: jruderman, Unassigned)

Tracking

(Blocks: 1 bug, {perf})

Trunk
Points:
---
Dependency tree / graph

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

7 years ago
See https://bugzilla.mozilla.org/show_bug.cgi?id=705597#c51 to #c53. It's odd that "s.indexOf(c) == 0" is faster than the alternatives, since it has to do more work.

We should optimize at least one of the following, and maybe all of them, down to some guards followed by a strcmp.

  if (s.indexOf("about:") == 0)

    In a simple implementation, this scans the entire string.
    It's currently the fastest!

  if (/^about:/.test(s))

    In a simple implementation, this creates a regexp each time through the 
    loop, along with updating regexp statics.

  if (s.substr(0, 6) == "about:")

    In a simple implementation, this allocates a new string before comparing.
The best candidate to optimize here is the /^literal/.test version --- fewer moving parts, and we already avoid the regexp cloning (using TI to determine the cloned regexp won't escape).  We still go through the regexp machinery though.  Is bug 705597 running chrome or content code?  TI is turned off in chrome code, and non-compileAndGo (chrome) stuff is generally a good deal slower than compileAndGo (content) stuff in JM, for various reasons.  We will get parity between the two with compartment-per-global (which will make all code compileAndGo).
Bug 705597 is chrome (sessionstore code) which runs every few seconds if you're active, generally, and currently blocks the main ui thread.
(Reporter)

Updated

7 years ago
Depends on: 650353
Summary: Sane methods of checking which strings start with a (constant) string are slow → Sane methods of checking which strings start with a (constant) string are slow in chrome code
Blocks: 579390
(Reporter)

Comment 3

7 years ago
ES6 will have String.prototype.startsWith :)

http://blog.cdleary.com/2012/01/accomplish-your-new-years-resolution-of-being-more-badass/
(Reporter)

Comment 4

7 years ago
A trick from bug 728780:

  if (s.lastIndexOf("about", 0) === 0)

The second param to lastIndexOf is the key: it says to start searching backwards from the beginning of the string.
startsWith landed quite some time ago. Can we close this now? Is it as fast as indexOf() == 0?
(In reply to Tim Taubert [:ttaubert] (on PTO, back Mon Sep 9th) from comment #5)
> startsWith landed quite some time ago. Can we close this now? Is it as fast
> as indexOf() == 0?

Quick micro-benchmark shows it's faster than indexOf / lastIndexOf(.., 0), so let's close this.
Status: NEW → RESOLVED
Last Resolved: 5 years ago
Resolution: --- → FIXED
FYI, we have ~30 uses in a trivial 'jsfind "ndexOf" | grep 0 | grep == | wc' (jsfind ~= find -name "*.js[m]" | xargs grep $*)

JSM files:
Most are in devtools and likely not critical (though would be nice to fix, most are in gcli).

The real ones are in SourceMap.jsp, PhoneNumber.jsm, Webapps.jsm, WspPduHelper.jsm, MmsPduHelper.jsm, utils.jsm and PlacesDBUtils.jsm

In js files there are a lot more.  A ton in tests, but also WifiWorker.js, android chrome, places, microformats, etc.  An estimate using grep -v to eliminate tests, etc got ~100.

We should fix any cases that might actually affect performance, and publicize this on MDN in the docs for indexOf/etc.
Keywords: dev-doc-needed

Updated

5 years ago
Resolution: FIXED → WORKSFORME
Keywords: dev-doc-needed
You need to log in before you can comment on or make changes to this bug.