skip to Main Content

At the moment I’ve used this code:

getGuid(): string {
    const guid = this.array[this.offset + 3].toString(16).padStart(2, '0') + this.array[this.offset + 2].toString(16).padStart(2, '0') + this.array[this.offset + 1].toString(16).padStart(2, '0') + this.array[this.offset + 0].toString(16).padStart(2, '0') + "-" +
        this.array[this.offset + 5].toString(16).padStart(2, '0') + this.array[this.offset + 4].toString(16).padStart(2, '0') + "-" +
        this.array[this.offset + 7].toString(16).padStart(2, '0') + this.array[this.offset + 6].toString(16).padStart(2, '0') + "-" +
        this.array[this.offset + 8].toString(16).padStart(2, '0') + this.array[this.offset + 9].toString(16).padStart(2, '0') + "-" +
        this.array[this.offset + 10].toString(16).padStart(2, '0') + this.array[this.offset + 11].toString(16).padStart(2, '0') + this.array[this.offset + 12].toString(16).padStart(2, '0') + this.array[this.offset + 13].toString(16).padStart(2, '0') + this.array[this.offset + 14].toString(16).padStart(2, '0') + this.array[this.offset + 15].toString(16).padStart(2, '0');
    this.offset += 16;
    return guid;
}

but I think it is highly inefficient, and has many gc overhead because of all the strings created. Problem is, I get thousand messages guids per second which I need to convert to strings. (it’s in browser not in a node application)

this.array is a Uint8Array

2

Answers


  1. In general, without a specific measurable problem, it’s hard to suggest solutions that could solve that problem. Without measurements (ideally real-world measurements rather than synthetic benchmarks), you don’t know whether what you’re doing improves things or makes them worse.

    That said, one thing that jumps out in this use case is that you’re recreating padded hex strings for the same 256 input values repeatedly. Given the volumes you’re seeing, you might do better to build those strings once and reuse them. That consumes a small bit of static memory to store the 256 strings, but avoids the repeated toString and padStart operations on every input GUID.

    A second thing you can do is cache the repeated property accesses to a local const.

    Example:

    // Build the strings once
    const byteStrings = Array.from({ length: 256 }, (_, value) =>
        value.toString(16).padStart(2, "0")
    );
    
    // Reuse them
    class Something {
        // ...
        getGuid(): string {
            const { array, offset } = this;
            const guid =
                byteStrings[array[offset + 3]] +
                byteStrings[array[offset + 2]] +
                byteStrings[array[offset + 1]] +
                byteStrings[array[offset + 0]] +
                "-" +
                byteStrings[array[offset + 5]] +
                byteStrings[array[offset + 4]] +
                "-" +
                byteStrings[array[offset + 7]] +
                byteStrings[array[offset + 6]] +
                "-" +
                byteStrings[array[offset + 8]] +
                byteStrings[array[offset + 9]] +
                "-" +
                byteStrings[array[offset + 10]] +
                byteStrings[array[offset + 11]] +
                byteStrings[array[offset + 12]] +
                byteStrings[array[offset + 13]] +
                byteStrings[array[offset + 14]] +
                byteStrings[array[offset + 15]];
            this.offset += 16;
            return guid;
        }
    }
    

    byteStrings could even just be a simple array literal, though the one-time creation loop shouldn’t be an issue:

    const byteStrings = [ "00", "01", "02", "03", "04", "05", "06", /*...*/, "ff"];
    

    But again, take both of these with a grain of salt, and profile/benchmark to see whether either helps.

    Login or Signup to reply.
  2. You can use typed arrays to access needed bytes:

    const arr = new Uint8Array(16);
    
    arr.forEach((_, idx) => arr[idx] = Math.random() * 256 | 0);
    
    console.log(...arr);
    
    console.log(getGuid(arr));
    console.log(originalGetGuid(arr));
    
    
    function getGuid(arr, offset = 0) {
    
        const reverseBytes = str => {
          let out = '';
          for(let i = str.length; i > 0; i-=2){
            out += str.slice(i - 2, i);
          }
          return out;
        }
        
        const paddings = [8, 2, 2, 2, 2, 8];
    
        return [
          new Uint32Array(arr.buffer, offset), 
          new Uint16Array(arr.buffer, offset += 4), 
          new Uint16Array(arr.buffer, offset += 2), 
          new Uint16Array(arr.buffer, offset += 2),
          new Uint16Array(arr.buffer, offset += 2), 
          new Uint32Array(arr.buffer, offset += 2), 
        ].reduce((r, [v], i) => {
          const str = v.toString(16).padStart(paddings[i]);
          return r + (i > 2 ? reverseBytes(str) : str) + (i < 4 ? '-' : '');
        }, '');
    }
    
    function originalGetGuid(array, offset = 0) {
        const guid = array[offset + 3].toString(16).padStart(2, '0') + array[offset + 2].toString(16).padStart(2, '0') + array[offset + 1].toString(16).padStart(2, '0') + array[offset + 0].toString(16).padStart(2, '0') + "-" +
            array[offset + 5].toString(16).padStart(2, '0') + array[offset + 4].toString(16).padStart(2, '0') + "-" +
            array[offset + 7].toString(16).padStart(2, '0') + array[offset + 6].toString(16).padStart(2, '0') + "-" +
            array[offset + 8].toString(16).padStart(2, '0') + array[offset + 9].toString(16).padStart(2, '0') + "-" +
            array[offset + 10].toString(16).padStart(2, '0') + array[offset + 11].toString(16).padStart(2, '0') + array[offset + 12].toString(16).padStart(2, '0') + array[offset + 13].toString(16).padStart(2, '0') + array[offset + 14].toString(16).padStart(2, '0') + array[offset + 15].toString(16).padStart(2, '0');
        offset += 16;
        return guid;
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search