Skip to content

[perf] DataView accessors, Array.concat, and regex match-with-groups are 4–30x slower than Hermes #6386

Description

@dlee

What happened

Three hot operations each lower to an opaque js_* runtime helper and land well
behind the Hermes interpreter. Perry 0.5.1220 vs Node v22 (V8) vs Hermes 1.0.0
(built from main), best of 5, macOS arm64; identical checksums across engines.

Op Perry Node Hermes Perry/Hermes
DataView set/getFloat64 (300×4096) 205 ms 1 ms 34 ms 6x
Array.prototype.concat (20000×1024) 686 ms 11 ms 23 ms 30x
regex .match() w/ 4 groups (300k) 237 ms 12 ms 67 ms ~3.5x

Regex matching without extraction (RegExp.test()) is separately fast — the
cost is in materializing capture arrays / accessor results, i.e. the helper
call, not the regex engine.

What you expected

At least Hermes-interpreter throughput on these ops.

Minimal reproduction

// DataView — 6x
function dv() { var N=4096, b=new ArrayBuffer(N*8), v=new DataView(b), a=0;
  for (var r=0;r<300;r++){ for(var i=0;i<N;i++) v.setFloat64(i*8,i*1.5+r,true);
    for(var i=0;i<N;i++) a+=v.getFloat64(i*8,true);} return Math.round(a); }

// Array.concat — 30x (arrays built once, concat isolated)
function cc() { var N=512,x=[],y=[]; for(var i=0;i<N;i++){x.push(i);y.push(i+N);}
  var a=0; for(var r=0;r<20000;r++){ a+=[].concat(x,y).length; } return a; }

// regex match with capture groups — ~3.5x
function rm() { var s="2026-07-13 key=42 val=99", re=/(\d{4})-(\d{2})-(\d{2}) key=(\d+)/, a=0;
  for (var i=0;i<300000;i++){ var m=s.match(re); if(m) a+=m[1].length+m[4].length; } return a; }
perry compile x.js -o x && ./x     # vs node x.js / hermes -O x.js

Environment

  • Perry version: 0.5.1220
  • Host OS: macOS 27.0 (arm64)
  • Target: native
  • Installed via: npm

Diagnostic output

DataView   perry 205ms | node 1ms  | hermes 34ms   (chk=3957657600 all)
concat     perry 686ms | node 11ms | hermes 23ms   (chk=20480000 all)
regexMatch perry 237ms | node 12ms | hermes 67ms   (chk=1800000 all)

Anything else

Likely instances of #6082 (helper declarations carry no LLVM attributes),
filed with per-op repros so each has a regression target — as typed-array
access got in #5525.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions