Home > other >  Is there a way to save space on keys of JS objects?
Is there a way to save space on keys of JS objects?

Time:03-14

I was just thinking about the following situation:

Let's say we have a line definition like shown below. Here start and end are both points.

let line = {
    start: {x:0, y:0},
    end: {x:0,y:0},
    orientation: 'vertical'
}

Now imagine we have a very large array of lines, how do we save space? I know you can replace the orientation value 'vertical' with an Enum. But can you save space on the key names without reducing readability? E.g., you can replace orientation with o, but now it is no longer clear what the key stands for.

Let me know!

CodePudding user response:

If you mean memory usage, Javascript Engines are very clever these days, things like using lookup's for keys internally, string de-duplication etc, make having short or long key names will have very little effect.

For example, using your data structure above I pushed 1 million records into an array, one with very long key names, and one with 1 characters key names. In both cases the memory usage per items worked out about 147 bytes. Also even using a const for the vertical had little effect.

But as you can see 147 bytes does seem high, so if you wanted to reduce this, you would need to use TypedArrays, unfortunately these can be a little bit more tricky to reason with. But if memory was a concern that might be worth the effort.

If you did use TypedArray you could use getters and setters to make this much easier. And doing this you could maybe use 33 bytes per record, 4 doubles & 1 byte.

But before doing anything, I would first make sure doing this sort of optimisation is even necessary. Pre-Optimising Javascript is a fools errand.

ps. I did the memory tests using NodeJs, that basically uses Chrome's Javascript engine.

Also if you want to play with how memory is effected, and you have NodeJs installed, here is some example code to get you started.

const oused = process.memoryUsage().heapUsed;

const values = [];
for (let l = 0; l < 1000000; l  = 1) {
    values.push({
        start: { x: 0, y: 0 },
        end: { x: 0, y: 0 },
        orientation: "vertical",
    });
}

console.log(process.memoryUsage().heapUsed - oused);

CodePudding user response:

Here's a representation of a line that strikes a balance between usability and memory efficiency. It uses no string identifiers because the positions of the data are encoded into the type. It also uses standard arrays because you didn't specify the size of the cartesian coordinate plane (so I can't suggest a bounded container like a TypedArray):

TS Playground

type Point = [x: number, y: number];

type Line = [a: Point, b: Point];
const line: Line = [[0, 0], [0, 2]];

// More memory efficient: 2 fewer arrays per line:
type CompactLine = [...a: Point, ...b: Point];
const compactLine: CompactLine = [0, 0, 0, 2];

CodePudding user response:

I suggest you create a map for all the shortened version of the keys and use the map in parallel with your object. The map can have the object keys as the map keys and the full form as the values

const map = new Map()
const object = {
  o: 4
} // o means orientation
map.set("o", "orientation")
const mapKeys = Array.from(map.keys())
const redeableObj = {}
mapKeys.forEach(key => {
  const redeableKey = map.get(key)
  redeableObj[redeableKey] = object[key]
})
console.log(object)
console.log(redeableObj)

  • Related