Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Static Hermes for React Native #48531

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

piaskowyk
Copy link
Contributor

@piaskowyk piaskowyk commented Jan 8, 2025

Summary:

This PR proposes changes to React Native to adopt the latest version of static Hermes. I've already made required changes for Hermes code, which you can view facebook/hermes#1566

Here's an overview of what's included:

  • Naming and Localization Updates: I've made several changes, including renaming libraries and updating the localization of binaries.
  • Build Script and CI Enhancements: I've updated the paths and build flags to align with the latest requirements.
  • Removal of Legacy Debugger: I've removed legacy debugger integration, as the latest Hermes version no longer supports these debugger symbols.

Remarks

  • I've used a .hermesversion file as a temporary workaround to test static Hermes from a specific commit until the proper tag is created.
  • I've used Static Hermes version from commit d6c8fe6f1a1135aa2528b775bbd4662c625c0088 - facebook/hermes@d6c8fe6 which is the newest commit for (08.01.2025)
  • I haven't implemented an opt-in mechanism yet (also I don't know if it's necessary to implement) because I want to discuss my vision with you before proceeding.
  • I acknowledge that these changes are potentially a bit intrusive, so I am open to discussion and any suggestions.

Benchmarks

The new implementation of Hermes offers a significant performance boost. Below are results of nBody benchmark.

Platform Variant Regular Hermes [ms] Static Hermes [ms] Improvements [%]
Android Debug 1826.31 1222.32 33.07%
iOS Debug 1286.91 858.08 33.32%
Android Release 1087.47 727.5 33.10%
iOS Release 892.15 541.65 39.28%

Tested on physical devices:

  • Android - Google Pixel 6
  • iOS - Phone 14
Benchmark source code
const PI = Math.PI;
const SOLAR_MASS = 4 * PI * PI;
const DAYS_PER_YEAR = 365.24;

class Body {
  x;
  y;
  z;
  vx;
  vy;
  vz;
  mass;

  constructor(
    x,
    y,
    z,
    vx,
    vy,
    vz,
    mass
  ) {
    this.x = x;
    this.y = y;
    this.z = z;
    this.vx = vx;
    this.vy = vy;
    this.vz = vz;
    this.mass = mass;
  }
}

function Jupiter() {
  return new Body(
    4.8414314424647209,
    -1.16032004402742839,
    -1.03622044471123109e-1,
    1.66007664274403694e-3 * DAYS_PER_YEAR,
    7.69901118419740425e-3 * DAYS_PER_YEAR,
    -6.90460016972063023e-5 * DAYS_PER_YEAR,
    9.54791938424326609e-4 * SOLAR_MASS
  );
}

function Saturn() {
  return new Body(
    8.34336671824457987,
    4.12479856412430479,
    -4.03523417114321381e-1,
    -2.76742510726862411e-3 * DAYS_PER_YEAR,
    4.99852801234917238e-3 * DAYS_PER_YEAR,
    2.30417297573763929e-5 * DAYS_PER_YEAR,
    2.85885980666130812e-4 * SOLAR_MASS
  );
}

function Uranus() {
  return new Body(
    1.2894369562139131e1,
    -1.51111514016986312e1,
    -2.23307578892655734e-1,
    2.96460137564761618e-3 * DAYS_PER_YEAR,
    2.3784717395948095e-3 * DAYS_PER_YEAR,
    -2.96589568540237556e-5 * DAYS_PER_YEAR,
    4.36624404335156298e-5 * SOLAR_MASS
  );
}

function Neptune() {
  return new Body(
    1.53796971148509165e1,
    -2.59193146099879641e1,
    1.79258772950371181e-1,
    2.68067772490389322e-3 * DAYS_PER_YEAR,
    1.62824170038242295e-3 * DAYS_PER_YEAR,
    -9.5159225451971587e-5 * DAYS_PER_YEAR,
    5.15138902046611451e-5 * SOLAR_MASS
  );
}

function Sun() {
  return new Body(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, SOLAR_MASS);
}

const bodies = [Sun(), Jupiter(), Saturn(), Uranus(), Neptune()];

function offsetMomentum(): void {
  let px = 0;
  let py = 0;
  let pz = 0;
  const size = bodies.length;
  for (let i = 0; i < size; i++) {
    const body = bodies[i];
    const mass = body.mass;
    px += body.vx * mass;
    py += body.vy * mass;
    pz += body.vz * mass;
  }

  const body = bodies[0];
  body.vx = -px / SOLAR_MASS;
  body.vy = -py / SOLAR_MASS;
  body.vz = -pz / SOLAR_MASS;
}

function advance(dt) {
  const size = bodies.length;

  for (let i = 0; i < size; i++) {
    const bodyi = bodies[i];
    let vxi = bodyi.vx;
    let vyi = bodyi.vy;
    let vzi = bodyi.vz;
    for (let j = i + 1; j < size; j++) {
      const bodyj = bodies[j];
      const dx = bodyi.x - bodyj.x;
      const dy = bodyi.y - bodyj.y;
      const dz = bodyi.z - bodyj.z;

      const d2 = dx * dx + dy * dy + dz * dz;
      const mag = dt / (d2 * Math.sqrt(d2));

      const massj = bodyj.mass;
      vxi -= dx * massj * mag;
      vyi -= dy * massj * mag;
      vzi -= dz * massj * mag;

      const massi = bodyi.mass;
      bodyj.vx += dx * massi * mag;
      bodyj.vy += dy * massi * mag;
      bodyj.vz += dz * massi * mag;
    }
    bodyi.vx = vxi;
    bodyi.vy = vyi;
    bodyi.vz = vzi;
  }

  for (let i = 0; i < size; i++) {
    const body = bodies[i];
    body.x += dt * body.vx;
    body.y += dt * body.vy;
    body.z += dt * body.vz;
  }
}

function energy() {
  let e = 0;
  const size = bodies.length;

  for (let i = 0; i < size; i++) {
    const bodyi = bodies[i];

    e +=
      0.5 *
      bodyi.mass *
      (bodyi.vx * bodyi.vx + bodyi.vy * bodyi.vy + bodyi.vz * bodyi.vz);

    for (let j = i + 1; j < size; j++) {
      const bodyj = bodies[j];
      const dx = bodyi.x - bodyj.x;
      const dy = bodyi.y - bodyj.y;
      const dz = bodyi.z - bodyj.z;

      const distance = Math.sqrt(dx * dx + dy * dy + dz * dz);
      e -= (bodyi.mass * bodyj.mass) / distance;
    }
  }
  return e;
}

function nbody() {
  const n = 400_000;
  //const n = 100;

  offsetMomentum();
  for (let i = 0; i < n; i++) {
    advance(0.01);
  }

  return energy();
}

function runTest() {
  const start = performance.now();
  const result = nbody();
  const end = performance.now();
  console.log(`energy: ${result}`);
  console.log(`time: ${end - start}`);
}

Changelog:

[GENERAL] [CHANGED] - Support for Static Hermes

Test Plan:

Just run RNTester app.

@facebook-github-bot facebook-github-bot added CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Software Mansion Partner: Software Mansion Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team. labels Jan 8, 2025
@huntie
Copy link
Member

huntie commented Jan 10, 2025

Hey @piaskowyk,

Removal of Legacy Debugger — unfortunately, we still depend on these codepaths in some apps in the Meta codebase. We're going to need some validation/updates on our side around this, so that's at least one blocker. Am taking a look to understand.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. p: Software Mansion Partner: Software Mansion Partner Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants