Bug 244754

Summary: [JSC] Optimize String#substring
Product: WebKit Reporter: Jarred Sumner <jarred>
Component: JavaScriptCoreAssignee: Yusuke Suzuki <ysuzuki>
Status: RESOLVED FIXED    
Severity: Normal CC: mark.lam, webkit-bug-importer, ysuzuki
Priority: P2 Keywords: InRadar
Version: WebKit Nightly Build   
Hardware: Unspecified   
OS: Unspecified   

Description Jarred Sumner 2022-09-02 20:17:59 PDT
❯ jsc foo.mjs
cpu: unknown
runtime: unknown (unknown)

benchmark                                        time (avg)             (min … max)       p75       p99      p995
----------------------------------------------------------------------------------- -----------------------------
startsWith                                       11 ns/iter   (10.51 ns … 21.54 ns)  10.78 ns  15.12 ns  15.71 ns
prototype_startsWith                          34.36 ns/iter  (32.08 ns … 150.64 ns)  34.63 ns  39.24 ns  80.12 ns
_startsWith                                   38.76 ns/iter  (36.85 ns … 124.11 ns)  39.07 ns  47.63 ns  81.98 ns
substring(0,8)                                36.64 ns/iter  (34.45 ns … 148.93 ns)  37.06 ns   45.9 ns  74.68 ns
substring(0, length) === (substr strict)      38.45 ns/iter  (36.84 ns … 155.19 ns)  38.82 ns  47.86 ns  75.75 ns
substring(0, length) == (substr non-strict)   38.76 ns/iter   (36.8 ns … 130.45 ns)   39.1 ns  47.66 ns  69.83 ns
indexOf strict                                15.75 ns/iter   (15.49 ns … 24.07 ns)  15.55 ns  17.25 ns  17.47 ns
indexOf non-strict                            13.67 ns/iter      (13 ns … 18.34 ns)  14.52 ns  17.06 ns  17.14 ns


❯ node foo.mjs
cpu: Apple M1 Max
runtime: node v18.4.0 (arm64-darwin)

benchmark                                        time (avg)             (min … max)       p75       p99      p995
----------------------------------------------------------------------------------- -----------------------------
startsWith                                    19.11 ns/iter  (18.58 ns … 404.22 ns)  18.68 ns  23.09 ns  26.93 ns
prototype_startsWith                          16.19 ns/iter   (14.25 ns … 28.51 ns)  17.43 ns   23.3 ns  24.11 ns
_startsWith                                   16.14 ns/iter  (14.55 ns … 285.63 ns)   16.8 ns  21.92 ns  22.95 ns
substring(0,8)                                15.94 ns/iter   (14.25 ns … 48.39 ns)  16.06 ns  25.28 ns  28.27 ns
substring(0, length) === (substr strict)      15.34 ns/iter   (14.25 ns … 31.48 ns)  15.72 ns  22.83 ns  24.01 ns
substring(0, length) == (substr non-strict)   15.87 ns/iter   (14.25 ns … 31.93 ns)  15.82 ns  24.57 ns  25.63 ns
indexOf strict                                14.68 ns/iter    (13.88 ns … 21.2 ns)   14.8 ns  16.66 ns  16.98 ns
indexOf non-strict                            14.62 ns/iter   (14.29 ns … 18.91 ns)  14.46 ns   16.8 ns  17.02 ns



Code:

```
import { run, bench, baseline } from "./node_modules/mitata/src/cli.mjs";

function _startsWith(str, find) {
    return str.substring(0,find.length) === find
}

String.prototype._startsWith = function (find) {
    return this.substring(0,find.length) === find
}

baseline("startsWith", () => "/assets/omfg".startsWith('/assets/'));
baseline("prototype_startsWith", () => "/assets/omfg"._startsWith('/assets/'));
baseline("_startsWith", () => _startsWith("/assets/omfg", '/assets/'));
baseline("substring(0,8)", () => "/assets/omfg".substring(0,8) === '/assets/');
baseline("substring(0, length) === (substr strict)", () => "/assets/omfg".substring(0,'/assets/'.length) === '/assets/');
baseline("substring(0, length) == (substr non-strict)", () => "/assets/omfg".substring(0,'/assets/'.length) == '/assets/');
baseline("indexOf strict", () => "/assets/omfg".indexOf('/assets/') === 0);
baseline("indexOf non-strict", () => "/assets/omfg".indexOf('/assets/') == 0);

await run();
```
Comment 1 Yusuke Suzuki 2022-09-02 20:25:30 PDT
startsWith and indexOf are already nice.
I think we should handle substring, substr, slice in DFG to avoid type check for double / int32 etc. And some case, we should do constant folding.
Comment 2 Radar WebKit Bug Importer 2022-09-09 20:18:17 PDT
<rdar://problem/99770218>
Comment 3 Yusuke Suzuki 2022-09-29 17:12:31 PDT
Pull request: https://github.com/WebKit/WebKit/pull/4844
Comment 4 Yusuke Suzuki 2022-09-29 17:12:41 PDT
cpu: unknown
runtime: unknown (unknown)

benchmark                                        time (avg)             (min … max)       p75       p99      p995
----------------------------------------------------------------------------------- -----------------------------
startsWith                                     9.41 ns/iter    (9.28 ns … 18.68 ns)   9.32 ns   11.2 ns  11.49 ns
prototype_startsWith                          12.09 ns/iter    (4.33 ns … 89.69 ns)  15.72 ns  18.61 ns  21.42 ns
_startsWith                                    5.09 ns/iter    (4.33 ns … 12.08 ns)   5.13 ns   5.66 ns   9.95 ns
substring(0,8)                                 8.48 ns/iter     (8.4 ns … 10.31 ns)   8.45 ns   8.93 ns   9.05 ns
substring(0, length) === (substr strict)        8.5 ns/iter     (8.4 ns … 10.47 ns)   8.46 ns   8.99 ns   9.07 ns
substring(0, length) == (substr non-strict)    8.81 ns/iter    (8.71 ns … 10.49 ns)   8.77 ns    9.3 ns   9.38 ns
indexOf strict                                18.12 ns/iter   (17.99 ns … 20.33 ns)  18.29 ns  18.79 ns  19.03 ns
indexOf non-strict                            18.14 ns/iter      (17.99 ns … 21 ns)   18.3 ns  18.98 ns  19.18 ns
Comment 5 EWS 2022-09-30 09:26:38 PDT
Committed 255030@main (3de7e6fba239): <https://commits.webkit.org/255030@main>

Reviewed commits have been landed. Closing PR #4844 and removing active labels.