Skip to content

Commit 9b5149c

Browse files
seemkdyladan
andauthored
perf: improve hexToBase64 (#3178)
Co-authored-by: Daniel Dyla <[email protected]>
1 parent 406a059 commit 9b5149c

File tree

3 files changed

+40
-9
lines changed

3 files changed

+40
-9
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
88

99
### :rocket: (Enhancement)
1010

11+
* perf(opentelemetry-core): improve hexToBase64 performance [#3178](https://github.com/open-telemetry/opentelemetry-js/pull/3178)
1112
* feat(sdk-trace-base): move Sampler declaration into sdk-trace-base [#3088](https://github.com/open-telemetry/opentelemetry-js/pull/3088) @legendecas
1213
* fix(grpc-instrumentation): added grpc attributes in instrumentation [#3127](https://github.com/open-telemetry/opentelemetry-js/pull/3127) @andrewzenkov
1314
* feat: support latest `@opentelemetry/api` [#3177](https://github.com/open-telemetry/opentelemetry-js/pull/3177) @dyladan

packages/opentelemetry-core/src/platform/node/hex-to-base64.ts

+33-7
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,40 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16+
function intValue(charCode: number): number {
17+
// 0-9
18+
if (charCode >= 48 && charCode <= 57) {
19+
return charCode - 48;
20+
}
21+
22+
// a-f
23+
if (charCode >= 97 && charCode <= 102) {
24+
return charCode - 87;
25+
}
26+
27+
// A-F
28+
return charCode - 55;
29+
}
30+
31+
const buf8 = Buffer.alloc(8);
32+
const buf16 = Buffer.alloc(16);
33+
1634
export function hexToBase64(hexStr: string): string {
17-
const hexStrLen = hexStr.length;
18-
let hexAsciiCharsStr = '';
19-
for (let i = 0; i < hexStrLen; i += 2) {
20-
const hexPair = hexStr.substring(i, i + 2);
21-
const hexVal = parseInt(hexPair, 16);
22-
hexAsciiCharsStr += String.fromCharCode(hexVal);
35+
let buf;
36+
if (hexStr.length === 16) {
37+
buf = buf8;
38+
} else if (hexStr.length === 32) {
39+
buf = buf16;
40+
} else {
41+
buf = Buffer.alloc(hexStr.length / 2);
42+
}
43+
let offset = 0;
44+
45+
for (let i = 0; i < hexStr.length; i += 2) {
46+
const hi = intValue(hexStr.charCodeAt(i));
47+
const lo = intValue(hexStr.charCodeAt(i + 1));
48+
buf.writeUInt8((hi << 4) | lo, offset++);
2349
}
2450

25-
return Buffer.from(hexAsciiCharsStr, 'ascii').toString('base64');
51+
return buf.toString('base64');
2652
}

packages/opentelemetry-core/test/platform/hex-to-base64.test.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@ import { hexToBase64 } from '../../src/platform';
2020
describe('hexToBase64', () => {
2121
it('convert hex to base64', () => {
2222
const id1 = '7deb739e02e44ef2';
23-
const id2 = '46cef837b919a16ff26e608c8cf42c80';
23+
const id2 = '12abc034d567e89ff26e608c8cf42c80';
24+
const id3 = id2.toUpperCase();
2425
assert.strictEqual(hexToBase64(id1), 'fetzngLkTvI=');
25-
assert.strictEqual(hexToBase64(id2), 'Rs74N7kZoW/ybmCMjPQsgA==');
26+
assert.strictEqual(hexToBase64(id2), 'EqvANNVn6J/ybmCMjPQsgA==');
27+
assert.strictEqual(hexToBase64(id3), 'EqvANNVn6J/ybmCMjPQsgA==');
28+
// Don't use the preallocated path
29+
assert.strictEqual(hexToBase64(id2.repeat(2)), 'EqvANNVn6J/ybmCMjPQsgBKrwDTVZ+if8m5gjIz0LIA=');
2630
});
2731
});

0 commit comments

Comments
 (0)