Skip to content

Commit

Permalink
Switch from rusha to native (node:crypto) sha1 implementation (#329)
Browse files Browse the repository at this point in the history
* chore: add benchmarks rusha vs native

* chore: replace rusha with node:crypto

* chore(node/benchmarks): reorder results

* formatting

* bump package.json, update changelog

---------

Co-authored-by: Dylan Martin <[email protected]>
  • Loading branch information
kravetsone and dmarticus authored Jan 15, 2025
1 parent d9c8535 commit 4402254
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 37 deletions.
4 changes: 4 additions & 0 deletions posthog-node/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Next

# 4.4.0 - 2025-01-15

Switch from rusha to native (node:crypto) sha1 implementation

# 4.3.2 - 2024-12-11

1. REVERT: Fix bug where this SDK incorrectly sent `$feature_flag_called` events with null values when using `getFeatureFlagPayload`.
Expand Down
70 changes: 70 additions & 0 deletions posthog-node/benchmarks/rusha-vs-native.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// @ts-check

import { bench, run, summary } from "mitata";
import { createHash } from "node:crypto"
import pkg from 'rusha';
const { createHash: createHashRusha } = pkg;

// eslint-disable-next-line
const LONG_SCALE = 0xfffffffffffffff

// from https://github.com/PostHog/posthog-js-lite/blob/2baa794708d78d5d10940817c3768e47abe2da99/posthog-node/src/feature-flags.ts#L460-L465
function _hashRusha(key, distinctId, salt = '') {
// rusha is a fast sha1 implementation in pure javascript
const sha1Hash = createHashRusha()
sha1Hash.update(`${key}.${distinctId}${salt}`)
return parseInt(sha1Hash.digest('hex').slice(0, 15), 16) / LONG_SCALE
}

function _hash(key, distinctId, salt = '') {
const sha1Hash = createHash("sha1")
sha1Hash.update(`${key}.${distinctId}${salt}`)
return parseInt(sha1Hash.digest('hex').slice(0, 15), 16) / LONG_SCALE
}

summary(() => {
bench("_hash with rusha", () => {
_hashRusha("test", "user_id")
});

bench("_hash with native", () => {
_hash("test", "user_id")
});
});

await run();


// !NODE
// node benchmarks/rusha-vs-native.mjs
// clk: ~3.99 GHz
// cpu: AMD Ryzen 7 7700 8-Core Processor
// runtime: node 22.11.0 (x64-linux)

// benchmark avg (min … max) p75 p99 (min … top 1%)
// ------------------------------------------- -------------------------------
// _hash with rusha 12.10 µs/iter 7.25 µs █
// (4.66 µs … 1.27 ms) 116.62 µs █▄▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
// _hash with native 547.04 ns/iter 435.45 ns █
// (370.08 ns … 3.61 µs) 3.58 µs █▃▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

// summary
// _hash with native
// 22.12x faster than _hash with rusha

// !BUN
// bun benchmarks/rusha-vs-native.mjs
// clk: ~5.04 GHz
// cpu: AMD Ryzen 7 7700 8-Core Processor
// runtime: bun 1.1.37 (x64-linux)

// benchmark avg (min … max) p75 p99 (min … top 1%)
// ------------------------------------------- -------------------------------
// _hash with rusha 10.00 µs/iter 4.96 µs █
// (2.60 µs … 2.78 ms) 45.85 µs ▂█▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
// _hash with native 471.82 ns/iter 420.00 ns █
// (370.00 ns … 949.79 µs) 1.99 µs █▆▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁

// summary
// _hash with native
// 21.19x faster than _hash with rusha
8 changes: 4 additions & 4 deletions posthog-node/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "posthog-node",
"version": "4.3.2",
"version": "4.4.0",
"description": "PostHog Node.js integration",
"repository": {
"type": "git",
Expand All @@ -23,12 +23,12 @@
"module": "lib/index.esm.js",
"types": "lib/index.d.ts",
"dependencies": {
"axios": "^1.7.4",
"rusha": "^0.8.14"
"axios": "^1.7.4"
},
"devDependencies": {
"@types/node": "^18.0.0",
"commander": "^9.3.0"
"commander": "^9.3.0",
"mitata": "^1.0.21"
},
"keywords": [
"posthog",
Expand Down
5 changes: 2 additions & 3 deletions posthog-node/src/feature-flags.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createHash } from 'rusha'
import { createHash } from 'node:crypto'
import { FeatureFlagCondition, FlagProperty, PostHogFeatureFlag, PropertyGroup } from './types'
import { JsonType, PostHogFetchOptions, PostHogFetchResponse } from 'posthog-core/src'
import { safeSetTimeout } from 'posthog-core/src/utils'
Expand Down Expand Up @@ -458,8 +458,7 @@ class FeatureFlagsPoller {
// # uniformly distributed between 0 and 1, so if we want to show this feature to 20% of traffic
// # we can do _hash(key, distinct_id) < 0.2
function _hash(key: string, distinctId: string, salt: string = ''): number {
// rusha is a fast sha1 implementation in pure javascript
const sha1Hash = createHash()
const sha1Hash = createHash('sha1')
sha1Hash.update(`${key}.${distinctId}${salt}`)
return parseInt(sha1Hash.digest('hex').slice(0, 15), 16) / LONG_SCALE
}
Expand Down
23 changes: 0 additions & 23 deletions posthog-node/src/types/rusha.d.ts

This file was deleted.

4 changes: 2 additions & 2 deletions posthog-node/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"types": ["node", "rusha"],
"typeRoots": ["./node_modules/@types", "../node_modules/@types", "./src/types"]
"types": ["node"],
"typeRoots": ["./node_modules/@types", "../node_modules/@types"]
}
}
10 changes: 5 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7942,6 +7942,11 @@ minizlib@^2.1.1:
minipass "^3.0.0"
yallist "^4.0.0"

mitata@^1.0.21:
version "1.0.21"
resolved "https://registry.yarnpkg.com/mitata/-/mitata-1.0.21.tgz#525828c6306a5243da65b4d0574956f2572ca432"
integrity sha512-5HnbQJpz0Ub/7x7lxaxPhd3U3zXr7rD+24FIgEp/hjVE5wz6ye/pQRBrgH3MUK8KLy/FfPy/yfZbpi0sbmsNFg==

mixin-deep@^1.2.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
Expand Down Expand Up @@ -9223,11 +9228,6 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"

rusha@^0.8.14:
version "0.8.14"
resolved "https://registry.yarnpkg.com/rusha/-/rusha-0.8.14.tgz#a977d0de9428406138b7bb90d3de5dcd024e2f68"
integrity sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==

safe-array-concat@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb"
Expand Down

0 comments on commit 4402254

Please sign in to comment.