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(cbor): encodeCbor & encodeCborSequence #6311

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

Conversation

BlackAsLight
Copy link
Contributor

@BlackAsLight BlackAsLight commented Dec 28, 2024

This pull request rewrites the encodeCbor and encodeCborSequence functions to provide better performance via the unification of memory creation on the heap. Previously when it came to encoding arrays, objects and maps it required creating lots of little bits of memory for each value and then at the end creating additional memory to concatenate it all together. These changes take a new approach, instead with the trade off being double iteration of arrays, objects and maps to first calculate the size that the input would end up being to create one uniform piece of memory and then fill it linearly in on the second iteration.

  • The encoding of undefined, null, booleans, and dates are all doing better than previously.
  • Small numbers and bigints are doing a little better than before, and big numbers and bigints are doing a little worse than before, but still better than the versions before v0.1.3.
    • I think the performance that came to arrays, objects and maps out ways the penalty here.
  • Strings smaller than 2 ** 16 in byte length, and Uint8Arrays smaller than 2 ** 32 outperform the current version, but interestedly do worse with longer lengths.
  • Encoding of the CborTag class is slower than the current version, but I'm not really sure why.
  • Finally, arrays, objects and maps see performance gains of 7x-15x, 3.5x-4x, and 3x-3.5x respectively.
Benchmark Source Code
  • std/cbor/deno.json
{
  "name": "@std/cbo",
  "version": "0.1.3",
  "exports": {
    ".": "./mod.ts",
    "./array-encoder-stream": "./array_encoder_stream.ts",
    "./byte-encoder-stream": "./byte_encoder_stream.ts",
    "./decode-cbor-sequence": "./decode_cbor_sequence.ts",
    "./decode-cbor": "./decode_cbor.ts",
    "./encode-cbor-sequence": "./encode_cbor_sequence.ts",
    "./encode-cbor": "./encode_cbor.ts",
    "./map-encoder-stream": "./map_encoder_stream.ts",
    "./sequence-decoder-stream": "./sequence_decoder_stream.ts",
    "./sequence-encoder-stream": "./sequence_encoder_stream.ts",
    "./tag": "./tag.ts",
    "./text-encoder-stream": "./text_encoder_stream.ts",
    "./types": "./types.ts"
  }
}
  • std/bench.ts
import { CborTag, encodeCbor as encodeCbor1 } from "jsr:@std/cbor";
import { encodeCbor as encodeCbor2 } from "jsr:@std/cbo";

function random(start: number, end: number): number {
  return Math.floor(Math.random() * (end - start) + start);
}

const Boolean = !Math.floor(Math.random() * 2);
const Float = Math.random() * 2 ** 8;
const Byte0 = random(0, 24);
const Byte1 = random(24, 2 ** 8);
const Byte2 = random(2 ** 8, 2 ** 16);
const Byte4 = random(2 ** 16, 2 ** 32);
const Byte8 = random(2 ** 32, 2 ** 64);
const BigByte0 = BigInt(random(0, 24));
const BigByte1 = BigInt(random(24, 2 ** 8));
const BigByte2 = BigInt(random(2 ** 8, 2 ** 16));
const BigByte4 = BigInt(random(2 ** 16, 2 ** 32));
const BigByte8 = BigInt(random(2 ** 32, 2 ** 64));
const String0 = "a".repeat(random(0, 24));
const String1 = "a".repeat(random(24, 2 ** 8));
const String2 = "a".repeat(random(2 ** 8, 2 ** 16));
const String4 = "a".repeat(random(2 ** 16, 2 ** 17));
const Uint8Array0 = new Uint8Array(random(0, 24));
const Uint8Array1 = new Uint8Array(random(24, 2 ** 8));
const Uint8Array2 = new Uint8Array(random(2 ** 8, 2 ** 16));
const Uint8Array4 = new Uint8Array(random(2 ** 16, 2 ** 32));
const Uint8Array8 = new Uint8Array(random(2 ** 32, 2 ** 33));
const Now = new Date();
const Tag = new CborTag(3, random(0, 24));

const Array0 = new Array(random(0, 24)).fill(0);
const Array1 = new Array(random(24, 2 ** 8)).fill(0);
const Array2 = new Array(random(2 ** 8, 2 ** 16)).fill(0);
const Array4 = new Array(random(2 ** 16, 2 ** 17)).fill(0);
const Object0 = Object.fromEntries(Array0.map((_, i) => [i, i]));
const Object1 = Object.fromEntries(Array1.map((_, i) => [i, i]));
const Object2 = Object.fromEntries(Array2.map((_, i) => [i, i]));
const Object4 = Object.fromEntries(Array4.map((_, i) => [i, i]));
const Map0 = new Map(Object.entries(Object0));
const Map1 = new Map(Object.entries(Object1));
const Map2 = new Map(Object.entries(Object2));
const Map4 = new Map(Object.entries(Object4));

Deno.bench({ name: "Current: Undefined", group: "Undefined" }, () => {
  encodeCbor1(undefined);
});

Deno.bench({ name: "New: Undefined", group: "Undefined" }, () => {
  encodeCbor2(undefined);
});

Deno.bench({ name: "Current: Null", group: "Null" }, () => {
  encodeCbor1(null);
});

Deno.bench({ name: "New: Null", group: "Null" }, () => {
  encodeCbor2(null);
});

Deno.bench({ name: "Current: Boolean", group: "Boolean" }, () => {
  encodeCbor1(Boolean);
});

Deno.bench({ name: "New: Boolean", group: "Boolean" }, () => {
  encodeCbor2(Boolean);
});

Deno.bench({ name: "Current: Float", group: "Float" }, () => {
  encodeCbor1(Float);
});

Deno.bench({ name: "New: Float", group: "Float" }, () => {
  encodeCbor2(Float);
});

Deno.bench({ name: "Current: Number0", group: "Number0" }, () => {
  encodeCbor1(Byte0);
});

Deno.bench({ name: "New: Number0", group: "Number0" }, () => {
  encodeCbor2(Byte0);
});

Deno.bench({ name: "Current: Number1", group: "Number1" }, () => {
  encodeCbor1(Byte1);
});

Deno.bench({ name: "New: Number1", group: "Number1" }, () => {
  encodeCbor2(Byte1);
});

Deno.bench({ name: "Current: Number2", group: "Number2" }, () => {
  encodeCbor1(Byte2);
});

Deno.bench({ name: "New: Number2", group: "Number2" }, () => {
  encodeCbor2(Byte2);
});

Deno.bench({ name: "Current: Number4", group: "Number4" }, () => {
  encodeCbor1(Byte4);
});

Deno.bench({ name: "New: Number4", group: "Number4" }, () => {
  encodeCbor2(Byte4);
});

Deno.bench({ name: "Current: Number8", group: "Number8" }, () => {
  encodeCbor1(Byte8);
});

Deno.bench({ name: "New: Number8", group: "Number8" }, () => {
  encodeCbor2(Byte8);
});

Deno.bench({ name: "Current: BigInt0", group: "BigInt0" }, () => {
  encodeCbor1(BigByte0);
});

Deno.bench({ name: "New: BigInt0", group: "BigInt0" }, () => {
  encodeCbor2(BigByte0);
});

Deno.bench({ name: "Current: BigInt1", group: "BigInt1" }, () => {
  encodeCbor1(BigByte1);
});

Deno.bench({ name: "New: BigInt1", group: "BigInt1" }, () => {
  encodeCbor2(BigByte1);
});

Deno.bench({ name: "Current: BigInt2", group: "BigInt2" }, () => {
  encodeCbor1(BigByte2);
});

Deno.bench({ name: "New: BigInt2", group: "BigInt2" }, () => {
  encodeCbor2(BigByte2);
});

Deno.bench({ name: "Current: BigInt4", group: "BigInt4" }, () => {
  encodeCbor1(BigByte4);
});

Deno.bench({ name: "New: BigInt4", group: "BigInt4" }, () => {
  encodeCbor2(BigByte4);
});

Deno.bench({ name: "Current: BigInt8", group: "BigInt8" }, () => {
  encodeCbor1(BigByte8);
});

Deno.bench({ name: "New: BigInt8", group: "BigInt8" }, () => {
  encodeCbor2(BigByte8);
});

Deno.bench({ name: "Current: String0", group: "String0" }, () => {
  encodeCbor1(String0);
});

Deno.bench({ name: "New: String0", group: "String0" }, () => {
  encodeCbor2(String0);
});

Deno.bench({ name: "Current: String1", group: "String1" }, () => {
  encodeCbor1(String1);
});

Deno.bench({ name: "New: String1", group: "String1" }, () => {
  encodeCbor2(String1);
});

Deno.bench({ name: "Current: String2", group: "String2" }, () => {
  encodeCbor1(String2);
});

Deno.bench({ name: "New: String2", group: "String2" }, () => {
  encodeCbor2(String2);
});

Deno.bench({ name: "Current: String4", group: "String4" }, () => {
  encodeCbor1(String4);
});

Deno.bench({ name: "New: String4", group: "String4" }, () => {
  encodeCbor2(String4);
});

Deno.bench({ name: "Current: Uint8Array0", group: "Uint8Array0" }, () => {
  encodeCbor1(Uint8Array0);
});

Deno.bench({ name: "New: Uint8Array0", group: "Uint8Array0" }, () => {
  encodeCbor2(Uint8Array0);
});

Deno.bench({ name: "Current: Uint8Array1", group: "Uint8Array1" }, () => {
  encodeCbor1(Uint8Array1);
});

Deno.bench({ name: "New: Uint8Array1", group: "Uint8Array1" }, () => {
  encodeCbor2(Uint8Array1);
});

Deno.bench({ name: "Current: Uint8Array2", group: "Uint8Array2" }, () => {
  encodeCbor1(Uint8Array2);
});

Deno.bench({ name: "New: Uint8Array2", group: "Uint8Array2" }, () => {
  encodeCbor2(Uint8Array2);
});

Deno.bench({ name: "Current: Uint8Array4", group: "Uint8Array4" }, () => {
  encodeCbor1(Uint8Array4);
});

Deno.bench({ name: "New: Uint8Array4", group: "Uint8Array4" }, () => {
  encodeCbor2(Uint8Array4);
});

Deno.bench({ name: "Current: Uint8Array8", group: "Uint8Array8" }, () => {
  encodeCbor1(Uint8Array8);
});

Deno.bench({ name: "New: Uint8Array8", group: "Uint8Array8" }, () => {
  encodeCbor2(Uint8Array8);
});

Deno.bench({ name: "Current: Date", group: "Date" }, () => {
  encodeCbor1(Now);
});

Deno.bench({ name: "New: Date", group: "Date" }, () => {
  encodeCbor2(Now);
});

Deno.bench({ name: "Current: CborTag", group: "CborTag" }, () => {
  encodeCbor1(Tag);
});

Deno.bench({ name: "New: CborTag", group: "CborTag" }, () => {
  encodeCbor2(Tag);
});

Deno.bench({ name: "Current: Array0", group: "Array0" }, () => {
  encodeCbor1(Array0);
});

Deno.bench({ name: "New: Array0", group: "Array0" }, () => {
  encodeCbor2(Array0);
});

Deno.bench({ name: "Current: Array1", group: "Array1" }, () => {
  encodeCbor1(Array1);
});

Deno.bench({ name: "New: Array1", group: "Array1" }, () => {
  encodeCbor2(Array1);
});

Deno.bench({ name: "Current: Array2", group: "Array2" }, () => {
  encodeCbor1(Array2);
});

Deno.bench({ name: "New: Array2", group: "Array2" }, () => {
  encodeCbor2(Array2);
});

Deno.bench({ name: "Current: Array4", group: "Array4" }, () => {
  encodeCbor1(Array4);
});

Deno.bench({ name: "New: Array4", group: "Array4" }, () => {
  encodeCbor2(Array4);
});

Deno.bench({ name: "Current: Object0", group: "Object0" }, () => {
  encodeCbor1(Object0);
});

Deno.bench({ name: "New: Object0", group: "Object0" }, () => {
  encodeCbor2(Object0);
});

Deno.bench({ name: "Current: Object1", group: "Object1" }, () => {
  encodeCbor1(Object1);
});

Deno.bench({ name: "New: Object1", group: "Object1" }, () => {
  encodeCbor2(Object1);
});

Deno.bench({ name: "Current: Object2", group: "Object2" }, () => {
  encodeCbor1(Object2);
});

Deno.bench({ name: "New: Object2", group: "Object2" }, () => {
  encodeCbor2(Object2);
});

Deno.bench({ name: "Current: Object4", group: "Object4" }, () => {
  encodeCbor1(Object4);
});

Deno.bench({ name: "New: Object4", group: "Object4" }, () => {
  encodeCbor2(Object4);
});

Deno.bench({ name: "Current: Map0", group: "Map0" }, () => {
  encodeCbor1(Map0);
});

Deno.bench({ name: "New: Map0", group: "Map0" }, () => {
  encodeCbor2(Map0);
});

Deno.bench({ name: "Current: Map1", group: "Map1" }, () => {
  encodeCbor1(Map1);
});

Deno.bench({ name: "New: Map1", group: "Map1" }, () => {
  encodeCbor2(Map1);
});

Deno.bench({ name: "Current: Map2", group: "Map2" }, () => {
  encodeCbor1(Map2);
});

Deno.bench({ name: "New: Map2", group: "Map2" }, () => {
  encodeCbor2(Map2);
});

Deno.bench({ name: "Current: Map4", group: "Map4" }, () => {
  encodeCbor1(Map4);
});

Deno.bench({ name: "New: Map4", group: "Map4" }, () => {
  encodeCbor2(Map4);
});
Benchmark Results
Check file:///Users/soul/Projects/std/bench.ts
    CPU | Apple M1
Runtime | Deno 2.1.4 (aarch64-apple-darwin)

file:///Users/soul/Projects/std/bench.ts

benchmark              time/iter (avg)        iter/s      (min … max)           p75      p99     p995
---------------------- ----------------------------- --------------------- --------------------------

group Undefined
Current: Undefined            243.1 ns     4,114,000 (172.2 ns … 728.7 ns) 252.1 ns 634.5 ns 638.3 ns
New: Undefined                192.7 ns     5,189,000 (128.9 ns … 629.9 ns) 188.2 ns 546.5 ns 552.5 ns

summary
  New: Undefined
     1.26x faster than Current: Undefined

group Null
Current: Null                 257.9 ns     3,878,000 (169.1 ns … 757.2 ns) 266.4 ns 723.3 ns 745.8 ns
New: Null                     202.4 ns     4,940,000 (129.1 ns … 605.2 ns) 207.6 ns 558.3 ns 575.6 ns

summary
  New: Null
     1.27x faster than Current: Null

group Boolean
Current: Boolean              250.7 ns     3,988,000 (178.5 ns … 670.5 ns) 256.3 ns 582.3 ns 662.5 ns
New: Boolean                  194.6 ns     5,140,000 (130.8 ns … 699.6 ns) 197.7 ns 626.4 ns 652.3 ns

summary
  New: Boolean
     1.29x faster than Current: Boolean

group Float
Current: Float                293.1 ns     3,411,000 (204.3 ns … 764.9 ns) 316.0 ns 699.8 ns 764.9 ns
New: Float                    368.4 ns     2,714,000 (220.6 ns … 941.0 ns) 465.0 ns 915.9 ns 941.0 ns

summary
  Current: Float
     1.26x faster than New: Float

group Number0
Current: Number0              291.6 ns     3,429,000 (171.6 ns … 892.3 ns) 365.7 ns 889.2 ns 892.3 ns
New: Number0                  220.8 ns     4,530,000 (140.8 ns … 625.2 ns) 224.9 ns 563.2 ns 574.0 ns

summary
  New: Number0
     1.32x faster than Current: Number0

group Number1
Current: Number1              286.6 ns     3,490,000 (172.7 ns … 796.4 ns) 339.8 ns 772.6 ns 796.4 ns
New: Number1                  230.4 ns     4,341,000 (144.2 ns … 647.8 ns) 260.2 ns 593.6 ns 594.9 ns

summary
  New: Number1
     1.24x faster than Current: Number1

group Number2
Current: Number2              354.9 ns     2,818,000 (232.3 ns … 915.3 ns) 407.1 ns 838.7 ns 915.3 ns
New: Number2                  312.1 ns     3,204,000 (223.4 ns … 842.5 ns) 326.9 ns 809.3 ns 842.5 ns

summary
  New: Number2
     1.14x faster than Current: Number2

group Number4
Current: Number4              390.0 ns     2,564,000 (233.3 ns … 967.2 ns) 503.6 ns 960.3 ns 967.2 ns
New: Number4                  442.3 ns     2,261,000 (298.1 ns …   1.1 µs) 526.0 ns   1.0 µs   1.1 µs

summary
  Current: Number4
     1.13x faster than New: Number4

group Number8
Current: Number8              347.2 ns     2,881,000 (229.8 ns …   1.4 µs) 367.1 ns   1.1 µs   1.4 µs
New: Number8                  429.1 ns     2,331,000 (284.0 ns …   1.0 µs) 502.7 ns   1.0 µs   1.0 µs

summary
  Current: Number8
     1.24x faster than New: Number8

group BigInt0
Current: BigInt0              347.4 ns     2,878,000 (227.6 ns … 971.1 ns) 377.8 ns 953.4 ns 971.1 ns
New: BigInt0                  308.6 ns     3,241,000 (216.5 ns … 811.9 ns) 334.1 ns 774.4 ns 811.9 ns

summary
  New: BigInt0
     1.13x faster than Current: BigInt0

group BigInt1
Current: BigInt1              346.3 ns     2,887,000 (228.6 ns …   1.0 µs) 392.7 ns 895.1 ns   1.0 µs
New: BigInt1                  351.7 ns     2,843,000 (242.5 ns … 900.3 ns) 400.9 ns 851.0 ns 900.3 ns

summary
  Current: BigInt1
     1.01x faster than New: BigInt1

group BigInt2
Current: BigInt2              429.7 ns     2,327,000 (290.7 ns …   1.1 µs) 512.5 ns 972.4 ns   1.1 µs
New: BigInt2                  464.0 ns     2,155,000 (343.8 ns …   1.2 µs) 493.2 ns   1.1 µs   1.2 µs

summary
  Current: BigInt2
     1.08x faster than New: BigInt2

group BigInt4
Current: BigInt4              509.7 ns     1,962,000 (313.9 ns …   1.2 µs) 593.0 ns   1.1 µs   1.2 µs
New: BigInt4                  553.9 ns     1,805,000 (377.9 ns …   1.3 µs) 657.8 ns   1.2 µs   1.3 µs

summary
  Current: BigInt4
     1.09x faster than New: BigInt4

group BigInt8
Current: BigInt8              419.5 ns     2,384,000 (263.6 ns …   1.1 µs) 467.1 ns   1.0 µs   1.1 µs
New: BigInt8                  515.1 ns     1,941,000 (381.6 ns …   1.2 µs) 586.1 ns   1.2 µs   1.2 µs

summary
  Current: BigInt8
     1.23x faster than New: BigInt8

group String0
Current: String0              954.1 ns     1,048,000 (608.0 ns …   1.9 µs)   1.1 µs   1.9 µs   1.9 µs
New: String0                  613.2 ns     1,631,000 (407.1 ns …   1.4 µs) 733.2 ns   1.4 µs   1.4 µs

summary
  New: String0
     1.56x faster than Current: String0

group String1
Current: String1              979.5 ns     1,021,000 (692.3 ns …   2.2 µs)   1.1 µs   2.2 µs   2.2 µs
New: String1                  721.1 ns     1,387,000 (502.0 ns …   1.7 µs) 778.5 ns   1.7 µs   1.7 µs

summary
  New: String1
     1.36x faster than Current: String1

group String2
Current: String2               15.2 µs        65,670 (  4.4 µs …   5.7 ms)  14.0 µs  58.2 µs 131.9 µs
New: String2                   17.3 µs        57,670 (  3.8 µs …   5.2 ms)  16.3 µs  70.0 µs 175.5 µs

summary
  Current: String2
     1.14x faster than New: String2

group String4
Current: String4               37.5 µs        26,660 (  9.2 µs …   5.3 ms)  34.8 µs 241.5 µs 455.1 µs
New: String4                   40.8 µs        24,490 (  8.7 µs …   5.8 ms)  35.3 µs 268.9 µs 485.6 µs

summary
  Current: String4
     1.09x faster than New: String4

group Uint8Array0
Current: Uint8Array0          586.8 ns     1,704,000 (356.8 ns …   1.4 µs) 724.3 ns   1.4 µs   1.4 µs
New: Uint8Array0              265.0 ns     3,773,000 (170.7 ns … 808.0 ns) 285.9 ns 751.4 ns 773.2 ns

summary
  New: Uint8Array0
     2.21x faster than Current: Uint8Array0

group Uint8Array1
Current: Uint8Array1          641.6 ns     1,559,000 (417.0 ns …   1.3 µs) 746.9 ns   1.3 µs   1.3 µs
New: Uint8Array1              295.9 ns     3,379,000 (192.5 ns … 785.2 ns) 343.0 ns 773.1 ns 785.2 ns

summary
  New: Uint8Array1
     2.17x faster than Current: Uint8Array1

group Uint8Array2
Current: Uint8Array2            4.2 µs       240,100 (  3.3 µs …   6.6 µs)   4.6 µs   6.6 µs   6.6 µs
New: Uint8Array2                3.0 µs       333,100 (  2.4 µs …   4.7 µs)   3.1 µs   4.7 µs   4.7 µs

summary
  New: Uint8Array2
     1.39x faster than Current: Uint8Array2

group Uint8Array4
Current: Uint8Array4          148.2 ms           6.7 (134.3 ms … 160.4 ms) 153.7 ms 160.4 ms 160.4 ms
New: Uint8Array4              143.5 ms           7.0 (114.8 ms … 173.3 ms) 166.5 ms 173.3 ms 173.3 ms

summary
  New: Uint8Array4
     1.03x faster than Current: Uint8Array4

group Uint8Array8
Current: Uint8Array8          828.0 ms           1.2 (672.1 ms …    1.2 s) 892.2 ms    1.2 s    1.2 s
New: Uint8Array8              777.6 ms           1.3 (702.0 ms … 856.3 ms) 828.9 ms 856.3 ms 856.3 ms

summary
  New: Uint8Array8
     1.06x faster than Current: Uint8Array8

group Date
Current: Date                   1.1 µs       931,700 (647.1 ns …   1.8 µs)   1.2 µs   1.8 µs   1.8 µs
New: Date                     637.7 ns     1,568,000 (356.6 ns …   1.2 µs) 783.4 ns   1.2 µs   1.2 µs

summary
  New: Date
     1.68x faster than Current: Date

group CborTag
Current: CborTag                1.5 µs       653,000 (831.6 ns …   2.4 µs)   1.6 µs   2.4 µs   2.4 µs
New: CborTag                    2.1 µs       480,100 (  1.3 µs …   3.1 µs)   2.3 µs   3.1 µs   3.1 µs

summary
  Current: CborTag
     1.36x faster than New: CborTag

group Array0
Current: Array0                 7.2 µs       138,500 (  5.4 µs …  11.5 µs)   7.9 µs  11.5 µs  11.5 µs
New: Array0                     1.1 µs       892,000 (699.1 ns …   2.9 µs)   1.5 µs   2.9 µs   2.9 µs

summary
  New: Array0
     6.44x faster than Current: Array0

group Array1
Current: Array1               104.5 µs         9,571 ( 41.8 µs …   1.7 ms) 144.2 µs 457.8 µs 618.9 µs
New: Array1                    12.6 µs        79,150 (  9.7 µs …   2.5 ms)  10.4 µs  37.4 µs  61.5 µs

summary
  New: Array1
     8.27x faster than Current: Array1

group Array2
Current: Array2                23.9 ms          41.8 ( 12.6 ms …  61.1 ms)  29.8 ms  61.1 ms  61.1 ms
New: Array2                     2.5 ms         393.6 (  2.0 ms …  13.1 ms)   2.7 ms   7.8 ms  11.8 ms

summary
  New: Array2
     9.42x faster than Current: Array2

group Array4
Current: Array4                49.1 ms          20.4 ( 29.5 ms …  79.7 ms)  57.1 ms  79.7 ms  79.7 ms
New: Array4                     4.8 ms         207.7 (  4.4 ms …   9.2 ms)   4.6 ms   9.2 ms   9.2 ms

summary
  New: Array4
    10.20x faster than Current: Array4

group Object0
Current: Object0               14.7 µs        68,060 (  8.0 µs …   4.0 ms)  12.6 µs  52.9 µs  92.0 µs
New: Object0                    5.3 µs       190,200 (  3.7 µs …   1.1 ms)   4.5 µs  12.5 µs  15.2 µs

summary
  New: Object0
     2.79x faster than Current: Object0

group Object1
Current: Object1              282.2 µs         3,544 (182.8 µs …   1.5 ms) 246.1 µs 944.7 µs   1.1 ms
New: Object1                  125.2 µs         7,985 ( 80.9 µs …   2.1 ms)  91.4 µs 514.7 µs 757.3 µs

summary
  New: Object1
     2.25x faster than Current: Object1

group Object2
Current: Object2              114.7 ms           8.7 ( 81.9 ms … 188.1 ms) 143.2 ms 188.1 ms 188.1 ms
New: Object2                   40.3 ms          24.8 ( 30.4 ms …  56.8 ms)  44.6 ms  56.8 ms  56.8 ms

summary
  New: Object2
     2.85x faster than Current: Object2

group Object4
Current: Object4              250.3 ms           4.0 (204.3 ms … 346.9 ms) 277.0 ms 346.9 ms 346.9 ms
New: Object4                   72.1 ms          13.9 ( 64.4 ms …  84.1 ms)  76.1 ms  84.1 ms  84.1 ms

summary
  New: Object4
     3.47x faster than Current: Object4

group Map0
Current: Map0                  15.6 µs        63,960 (  8.5 µs …   1.3 ms)  13.3 µs  59.1 µs  94.5 µs
New: Map0                       4.6 µs       217,200 (  3.1 µs … 948.2 µs)   3.8 µs  11.5 µs  15.8 µs

summary
  New: Map0
     3.40x faster than Current: Map0

group Map1
Current: Map1                 345.6 µs         2,894 (183.7 µs …   2.2 ms) 401.8 µs   1.3 ms   1.4 ms
New: Map1                     113.4 µs         8,822 ( 72.2 µs …   1.6 ms)  85.6 µs 415.1 µs 530.0 µs

summary
  New: Map1
     3.05x faster than Current: Map1

group Map2
Current: Map2                 104.6 ms           9.6 ( 83.7 ms … 165.1 ms) 110.3 ms 165.1 ms 165.1 ms
New: Map2                      32.4 ms          30.8 ( 23.2 ms …  51.3 ms)  36.8 ms  51.3 ms  51.3 ms

summary
  New: Map2
     3.23x faster than Current: Map2

group Map4
Current: Map4                 242.3 ms           4.1 (195.6 ms … 338.0 ms) 262.5 ms 338.0 ms 338.0 ms
New: Map4                      75.0 ms          13.3 ( 56.0 ms … 127.3 ms)  77.2 ms 127.3 ms 127.3 ms

summary
  New: Map4
     3.23x faster than Current: Map4

@BlackAsLight BlackAsLight requested a review from kt3k as a code owner December 28, 2024 11:47
@github-actions github-actions bot added the cbor label Dec 28, 2024
Copy link

codecov bot commented Dec 28, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 96.36%. Comparing base (e3dc30a) to head (9dbc437).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6311      +/-   ##
==========================================
+ Coverage   96.35%   96.36%   +0.01%     
==========================================
  Files         547      547              
  Lines       41671    41693      +22     
  Branches     6315     6321       +6     
==========================================
+ Hits        40151    40179      +28     
+ Misses       1479     1473       -6     
  Partials       41       41              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Comment on lines +116 to +123
if (isNegative && input <= -(2 ** 64)) {
throw new RangeError(
`Cannot encode number: It (${input}) exceeds -(2 ** 64) - 1`,
);
} else if (input >= 2 ** 64) {
throw new RangeError(
`Cannot encode number: It (${input}) exceeds 2 ** 64 - 1`,
);
Copy link
Contributor

@babiabeo babiabeo Dec 29, 2024

Choose a reason for hiding this comment

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

IMO, these checks can lead to inaccurate results due to floating-point precision error

For example, 2 ** 64 - 10 is still equal to 2 ** 64

Copy link
Contributor Author

Choose a reason for hiding this comment

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

While precision is lost with numbers larger than 2 ** 53, I've experienced they're still consistent in how the number is interpreted and removing them would just cause the error to be thrown later at DataView.setBigUInt64 instead and would be less clear on why they got an error.

@BlackAsLight
Copy link
Contributor Author

I noticed an error in my benchmark code for objects and maps, so the above benchmark code and results has been updated to fix that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants