# Number\[\] vs buffer performance

**URL:** <https://forum.makecode.com/t/number-vs-buffer-performance/31887>\
**Category:** Help\
**Tags:** extension\
**Created:** [November 22, 2024, 11:49pm UTC](https://forum.makecode.com/t/number-vs-buffer-performance/31887 "2024-11-22T23:49:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![chembot](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/chembot/32/14245_2.png) [@chembot](https://forum.makecode.com/u/chembot)\
**Post date:** [November 22, 2024, 11:49pm UTC](https://forum.makecode.com/t/number-vs-buffer-performance/31887/1 "2024-11-22T23:49:31Z")

</div>

I need to store 16 values in a class, representing a 4x4 grid of numbers. Initially I was using number but I know that’s slow. Converting to number and just doing `index = 4 * y + x` is easy enough, but I was wondering if I could make it faster.

I did some testing with a buffer, and it seems to be significantly slower. I tried both Float32LE and Float32BE and there didn’t seem to be much difference. I know I could also do something like `public v00: number, v01: number ... v32: number, v33: number` but that would be a pain to work with and loop through. Am I using buffers or getting and setting numbers incorrectly? Also, is this way of benchmarking at all accurate? Thanks.

Test code:

```auto
// initial setup, doesn't count for performance
// set up 16 element 1D array
let myArr: number[] = [];
for (let i = 0; i < 16; i++) {
    myArr.push(i);
}
// 4 bytes per float
let myBuf = Buffer.create(16 * 4);
let format = NumberFormat.Float32LE;

// actual test
let samples = 10;
let totals = [0, 0];
let n = 100000;

// do 2 sets and 1 get n times to each
for (let s = 0; s < samples; s++) {
    pause(1);
    let t0 = game.runtime();
    for (let i = 0; i < n; i++) {
        let index = i % 16;
        myArr[index] = i * 3.0;
        myArr[index] = myArr[index] / 2.2;
    }
    pause(1);
    let t1 = game.runtime();
    totals[0] += t1 - t0;
}

for (let s = 0; s < samples; s++) {
    pause(1);
    let t0 = game.runtime();
    for (let i = 0; i < n; i++) {
        let index = 4 * (i % 16);
        myBuf.setNumber(format, index, i * 3.0);
        myBuf.setNumber(format, index, myBuf.getNumber(format, index) / 2.2);
    }
    pause(1);
    let t1 = game.runtime();
    totals[1] += t1 - t0;
}

let averages = [totals[0] / samples, totals[1] / samples];
game.splash("arr: " + averages[0] + "ms", "buf: " + averages[1] + "ms");

```

---

<div class="post-metadata">

**Author:** ![richard](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/richard/32/5417_2.png) [@richard](https://forum.makecode.com/u/richard)\
**Post date:** [November 23, 2024, 12:03am UTC](https://forum.makecode.com/t/number-vs-buffer-performance/31887/2 "2024-11-23T00:03:06Z")

</div>

don’t put pauses into benchmarking code; use `control.millis()` instead of `game.runtime()` to get a more accurate value. `game.runtime()` is tied to the current frame which is why the pauses were causing it to change.

i would expect arrays to be faster, especially in the browser. buffers need to be packed/unpacked whenever numbers are read or written which is all overhead.

the place where buffers perform significantly better than arrays is in memory/code size. i expect they also perform a lot better in terms of allocation time for statically declared arrays.

for example:

```auto
// this requires an array to be allocated into memory and code
// to be generated for pushing each of the values into the array
let x = [1, 2, 3, 4]

// this requires no extra code generation and takes up no RAM if
// the buffer is read-only. writing to the buffer will move it into
// memory
let x = hex`1234`

```

for floating point numbers specifically, i think there isn’t much benefit to using buffers (unless they are read-only).

---

<div class="post-metadata">

**Author:** ![richard](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/richard/32/5417_2.png) [@richard](https://forum.makecode.com/u/richard)\
**Post date:** [November 23, 2024, 12:06am UTC](https://forum.makecode.com/t/number-vs-buffer-performance/31887/3 "2024-11-23T00:06:04Z")

</div>

oh also, are you doing this benchmarking on hardware or in the browser?

---

<div class="post-metadata">

**Author:** ![chembot](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/chembot/32/14245_2.png) [@chembot](https://forum.makecode.com/u/chembot)\
**Post date:** [November 23, 2024, 5:36am UTC](https://forum.makecode.com/t/number-vs-buffer-performance/31887/4 "2024-11-23T05:36:49Z")

</div>

I had been doing benchmarking in browser. I’ve swapped over to `control.millis()`, thanks for the info. I’m doing a lot of reading and writing so unfortunately a buffer won’t work here.

One thing I found was tuple types, which performed similarly to an array in testing but shouldn’t have the memory overhead. Something like:

```auto
type arr4x4 = [
    number, number, number, number,
    number, number, number, number,
    number, number, number, number,
    number, number, number, number
];

let myArr: arr4x4 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];

```

Although to avoid errors I had to do `(myArr as number[])[index]`.  
One other thing that worked was:

```auto
let myArrBase: arr4x4 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let myArr: number[] = myArrBase;
myArr[index] //works fine

```

Though I’m not 100% sure how having a `number[]` point to a tuple works.  
Is this solution worth pursuing, or should I just go for dynamic arrays and deal with higher memory use?

---

<div class="post-metadata">

**Author:** ![chembot](https://sea2.discourse-cdn.com/flex020/user_avatar/forum.makecode.com/chembot/32/14245_2.png) [@chembot](https://forum.makecode.com/u/chembot)\
**Post date:** [November 24, 2024, 4:56pm UTC](https://forum.makecode.com/t/number-vs-buffer-performance/31887/5 "2024-11-24T16:56:45Z")

</div>

Did some more experimenting with tuples. There was no difference in performance time wise, and it led to some unexpected behaviour. Having an array point to a tuple, or just casting the tuple to `number[]` allows addition of extra items. From what I can tell tuples are just arrays with limitations, and aren’t actually static. Just using arrays seems like best approach for now.  
Strange tuple code:

```auto
let myTup: [number, number] = [0,0];
let myArr: number[] = myTup;

myArr.push(4);
console.log(myTup.length) //prints 3
console.log(myTup[2]) // throws error

```

Similarly:

```auto
let myTup: [number, number] = [0, 0]
(myTup as number[]).push(5);

```
