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

perf: avoid using exceptions for flow control #1074

Merged
merged 2 commits into from
Nov 6, 2024

Conversation

beeme1mr
Copy link
Member

@beeme1mr beeme1mr commented Nov 1, 2024

This PR

  • avoids using error codes as flow control during an evaluation

@beeme1mr beeme1mr requested a review from a team as a code owner November 1, 2024 20:58
Copy link
Member

@lukas-reining lukas-reining left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice change! Even though this is more a "stylistic" change than a performance benefit.

@beeme1mr
Copy link
Member Author

beeme1mr commented Nov 5, 2024

Nice change! Even though this is more a "stylistic" change than a performance benefit

It should have some minor performance improvements but I need to run proper performance tests to prove it. 😄

Here's a fun snippet from Stack Overflow to see how impactful throwing an error is on performance.

import { performance } from "perf_hooks";

const error = new Error("invalid exception");
function ThrowException() {
  throw error;
}
const _ATTEMPT = 1000000;
function ThrowingExceptions() {
  const p1 = performance.now();
  for (let i = 0; i < _ATTEMPT; i++) {
    try {
      ThrowException();
    } catch (ex) {
      // log error
    }
  }
  const p2 = performance.now();
  console.log(`ThrowingExceptions: ${p2 - p1}`);
}
function ReturnException() {
  return { error };
}
function ReturningExceptions() {
  const p1 = performance.now();
  for (let i = 0; i < _ATTEMPT; i++) {
    const ex = ReturnException();
    if (ex.error) {
      // log error
    }
  }
  const p2 = performance.now();
  console.log(`ReturningExceptions: ${p2 - p1}`);
}

function Process() {
  ThrowingExceptions();
  ReturningExceptions();
  ThrowingExceptions();
  ReturningExceptions();
}

Process();

And here are the results on my computer.

ThrowingExceptions: 365.008125
ReturningExceptions: 3.436661000000015
ThrowingExceptions: 363.11218099999996
ReturningExceptions: 1.329001000000062

@lukas-reining
Copy link
Member

It should have some minor performance improvements but I need to run proper performance tests to prove it. 😄

Here's a fun snippet from Stack Overflow to see how impactful throwing an error is on performance.

Oh this is interesting @beeme1mr. I thought for V8 this would not affect the performance, had it in mind from some discussion I had in the past.
I do not think that this will affect our performance but I am also getting a little less than 100x performance for the test :D

ThrowingExceptions: 183.6151249408722
ReturningExceptions: 2.1167919635772705
ThrowingExceptions: 196.92433404922485
ReturningExceptions: 2.2545419931411743

When I inline the error creation, I consistently get faster times with the throw (and sure long times due to Error creation overhead):

ThrowingExceptions: 1596.49795794487
ReturningExceptions: 1687.1295830011368
ThrowingExceptions: 1605.3998750448227
ReturningExceptions: 1646.5373330116272
import { performance } from 'perf_hooks';

const _ATTEMPT = 1000000;

function ThrowingExceptions() {
  const p1 = performance.now();
  for (let i = 0; i < _ATTEMPT; i++) {
    try {
      throw new Error('invalid exception');
    } catch (ex) {
      // log error
    }
  }
  const p2 = performance.now();
  console.log(`ThrowingExceptions: ${p2 - p1}`);
}

function ReturnException() {
  return new Error('invalid exception');
}

function ReturningExceptions() {
  const p1 = performance.now();
  for (let i = 0; i < _ATTEMPT; i++) {
    const ex = ReturnException();
    if (ex) {
      // log error
    }
  }
  const p2 = performance.now();
  console.log(`ReturningExceptions: ${p2 - p1}`);
}

function Process() {
  ThrowingExceptions();
  ReturningExceptions();
  ThrowingExceptions();
  ReturningExceptions();
}

Process();

@beeme1mr
Copy link
Member Author

beeme1mr commented Nov 5, 2024

What version of node are you using? Perhaps performance has improved in recent versions. 🤔

@lukas-reining
Copy link
Member

What version of node are you using? Perhaps performance has improved in recent versions. 🤔

Tried Node 16, 20 and 22, all the same, and my Chrome so several V8 versions, I guess it simply is notable overhead when testing it in the synthetic benchmark. I guess in reality the error creation alone compensates the performance benefit, but as we are not creating errors here anymore I guess we can actually have a little performance improvement :)

@beeme1mr beeme1mr added this pull request to the merge queue Nov 6, 2024
Merged via the queue into main with commit 26264d6 Nov 6, 2024
8 checks passed
@beeme1mr beeme1mr deleted the avoid-exception-flow-control branch November 6, 2024 21:51
toddbaert pushed a commit that referenced this pull request Nov 7, 2024
🤖 I have created a release *beep* *boop*
---


##
[1.3.2](web-sdk-v1.3.1...web-sdk-v1.3.2)
(2024-11-07)


### 🐛 Bug Fixes

* update OpenFeature core version to 1.5.0
([#1077](#1077))
([a3469b6](a3469b6))


### 🧹 Chore

* loosen peer dependency requirements, remove some ci automation
([#1080](#1080))
([ef3ba21](ef3ba21))


### 🚀 Performance

* avoid using exceptions for flow control
([#1074](#1074))
([26264d6](26264d6))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <[email protected]>
beeme1mr pushed a commit that referenced this pull request Nov 7, 2024
🤖 I have created a release *beep* *boop*
---


##
[1.16.2](server-sdk-v1.16.1...server-sdk-v1.16.2)
(2024-11-07)


### 🧹 Chore

* loosen peer dependency requirements, remove some ci automation
([#1080](#1080))
([ef3ba21](ef3ba21))


### 🚀 Performance

* avoid using exceptions for flow control
([#1074](#1074))
([26264d6](26264d6))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Signed-off-by: OpenFeature Bot <[email protected]>
Signed-off-by: Todd Baert <[email protected]>
Co-authored-by: Todd Baert <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants