)]}'
{
  "commit": "c242d3a7563a5d5c6d0f8a56ad74a51b17f9fac9",
  "tree": "7ee2fe67701fadb911eb3143eb38956a05ae2791",
  "parents": [
    "23f0c0b27b3e797f9f7918735ad3461c34847b11"
  ],
  "author": {
    "name": "Jens Johansen",
    "email": "jensj@google.com",
    "time": "Wed Sep 25 07:33:40 2024 +0000"
  },
  "committer": {
    "name": "Commit Queue",
    "email": "dart-scoped@luci-project-accounts.iam.gserviceaccount.com",
    "time": "Wed Sep 25 07:33:40 2024 +0000"
  },
  "message": "[scanner] Use \u0027vm:unsafe:no-bounds-checks\u0027 and add explicit bounds checks\n\nThe (utf8) scanner currently has this thing where you give it a\n0-terminated byte-array (i.e. you read the file, then allocate\nsomething that\u0027s 1 bigger, copy the data, then give it to the scanner)\nto \u0027avoid bounds checks\u0027.\nDart still has bounds checks though - they\u0027re just implicit.\n\nAs for the string scanner ut gets a string, then creates a new string\nlike `string + \u0027\\x00\u0027` - so basically the same thing.\n\nThis CL uses the \u0027vm:unsafe:no-bounds-checks\u0027 pragma, removing the\nimplicit bounds checks, adding explicit bounds checks,\nsaving ~73.6 mio instructions when compiling the CFE in the process:\n\n```\nComparing snapshot #1 with snapshot #2\ncycles:u: -0.9983% +/- 0.6563% (-174026333.30 +/- 114410028.98)\ninstructions:u: -0.3416% +/- 0.0005% (-73659267.00 +/- 108567.20)\nbranch-misses:u: -4.8952% +/- 2.2612% (-3172939.50 +/- 1465641.18)\n```\n\nWith the scanner-benchmark with `--bytes` I get this:\n\n```\nmsec task-clock:u: -1.2251% +/- 0.6355% (-50.64 +/- 26.27)\ncycles:u: -1.2376% +/- 0.6385% (-223642830.80 +/- 115393789.68)\ninstructions:u: -2.8155% +/- 0.0000% (-1153243856.00 +/- 428.11)\nseconds time elapsed: -1.2165% +/- 0.6408% (-0.05 +/- 0.03)\nseconds user: -1.1539% +/- 0.6495% (-0.05 +/- 0.03)\n```\n\nWith the scanner-benchmark with `--string` I get this:\n\n```\nmsec task-clock:u: -7.6439% +/- 0.6628% (-366.08 +/- 31.74)\npage-faults:u: -95.0034% +/- 0.0014% (-228023.50 +/- 3.41)\ninstructions:u: 2.1041% +/- 0.0000% (897941907.60 +/- 2082.79)\nbranch-misses:u: 3.2994% +/- 1.4675% (3239735.30 +/- 1440940.88)\nseconds time elapsed: -7.6595% +/- 0.6610% (-0.37 +/- 0.03)\nseconds user: -0.8801% +/- 0.7676% (-0.04 +/- 0.03)\nseconds sys: -92.0140% +/- 2.8075% (-0.33 +/- 0.01)\nMarkSweep(   old space) goes from 6 to 0\nNotice combined GC time goes from 112 ms to 41 ms (notice only 1 run each).\n```\n\nWhere I\u0027ll note that the \u0027vm:unsafe:no-bounds-checks\u0027 pragma doesn\u0027t\n(yet?) work for `String.codeUnitAt`.\nSee https://dart-review.googlesource.com/c/sdk/+/384540\n(and https://dart-review.googlesource.com/c/sdk/+/385201) for details.\nI assume the relatively  big change here is caused by not allocating\na new string with a 0-byte in the end each time.\n\nNote that the read-allocate-copy dance is still performed for the utf8\nscanner in this CL as it requires changing all call-sites instead.\nIt will be done in a follow-up CL where the \"end-of-file\" int will\nlikely also be changed to `-1` to (I assume) allow for having the\n0-byte in the middle of a file (see also the 10+ year old bug at\nhttps://github.com/dart-lang/sdk/issues/18090)\n\nNote: The pragma (currently?) only has effect in AOT and this change\nwill (for the utf8 scanner) make the JIT version slower\n(probably by the same ~73.6 mio instructions as - at least in AOT -\nthe implicit check is 6 instructions and the explicit one is 3\ninstructions). As the pragma doesn\u0027t work in the StringScanner anyway\nI expect the change to be somewhat equivalent there. Once the\nread-allocate-copy dance is also removed from the utf8 scanner I expect\nthe combined result to be positive all around.\n\nUpdate: With https://dart-review.googlesource.com/c/sdk/+/385201 landed\nI get these changes:\n\nCompiling the CFE:\n```\ninstructions:u: -0.4520% +/- 0.0002% (-98470955.29 +/- 42253.40)\n```\n\nScanner benchmark with `--bytes`:\n\n```\nmsec task-clock:u: -2.1758% +/- 0.2316% (-92.07 +/- 9.80)\ncycles:u: -2.1941% +/- 0.2283% (-405224983.11 +/- 42160655.88)\ninstructions:u: -3.1049% +/- 0.0000% (-1272360052.95 +/- 706.54)\nbranch-misses:u: 2.4718% +/- 0.5142% (2371345.23 +/- 493257.76)\nseconds time elapsed: -2.1761% +/- 0.2317% (-0.09 +/- 0.01)\nseconds user: -2.2071% +/- 0.2308% (-0.09 +/- 0.01)\n```\n\nScanner benchmark with `--string`:\n\n```\nmsec task-clock:u: -15.0073% +/- 0.2175% (-745.93 +/- 10.81)\npage-faults:u: -95.0035% +/- 0.0003% (-228024.25 +/- 0.81)\ncycles:u: -7.7986% +/- 0.2329% (-1558985588.99 +/- 46560962.79)\ninstructions:u: -3.7054% +/- 0.0000% (-1581977447.66 +/- 481.68)\nbranch-misses:u: -0.6880% +/- 0.5818% (-689453.22 +/- 583101.50)\nseconds time elapsed: -15.0198% +/- 0.2170% (-0.75 +/- 0.01)\nseconds user: -8.8149% +/- 0.2648% (-0.41 +/- 0.01)\nseconds sys: -94.1247% +/- 1.6444% (-0.34 +/- 0.01)\nMarkSweep(   old space) goes from 6 to 0\n```\n\nChange-Id: I524a21f488da7df5dc9d2cdf40112b84896ad3e0\nReviewed-on: https://dart-review.googlesource.com/c/sdk/+/383324\nReviewed-by: Brian Wilkerson \u003cbrianwilkerson@google.com\u003e\nReviewed-by: Johnni Winther \u003cjohnniwinther@google.com\u003e\nCommit-Queue: Jens Johansen \u003cjensj@google.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "957005c7b44a8a8276b2c6519530b1ac94df8479",
      "old_mode": 33188,
      "old_path": "pkg/_fe_analyzer_shared/lib/src/scanner/string_scanner.dart",
      "new_id": "14b2e4b522b08e81ba8156205cd49a0b8ec35982",
      "new_mode": 33188,
      "new_path": "pkg/_fe_analyzer_shared/lib/src/scanner/string_scanner.dart"
    },
    {
      "type": "modify",
      "old_id": "764ea95eaf62038251d86bf6050bfe014088902c",
      "old_mode": 33188,
      "old_path": "pkg/_fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner.dart",
      "new_id": "7ea5cc8047a37a85adeb9aa0e426d71193625308",
      "new_mode": 33188,
      "new_path": "pkg/_fe_analyzer_shared/lib/src/scanner/utf8_bytes_scanner.dart"
    }
  ]
}
