skip to Main Content

Let’s say I have this ItemWrapper class that is used to generate many Items. Inside it’s constructor I’m using "Location Item" string that I know I will only use it in here.

class ItemWrapper {
  allItems = {};
  constructor(someItems = []){
    someItems.forEach(_item => {
      this.allItems.push(new Item({name: _item.Name, position: _item.position, type: "Location Item"}))
    })
  }
}

I read somewhere that it is a good practice to avoid object creations to save memory including string creations in loops like above. Let’s say I’m using ItemWrapper to create thousands of items and these kind of wrappers are used all over my codebase. I understand that most of the time having variables for strings is a good practise for code readability and reusability, but is there actually some performance benefit to extract that string in to variable like bellow?

class ItemWrapper {
  allItems = {};
  constructor(someItems = []){
    const LOCATION_ITEM = "Location Item";
    someItems.forEach(_item => {
      this.allItems.push(new Item({name: _item.Name, position: _item.position, type: LOCATION_ITEM }))
    })
  }
}

I’m not sure how to test this out, cause if it makes a difference, It would show up only when many classes like this are used and all the memory allocations would be spread all over an entire app.

2

Answers


  1. According to this experiment there is no significant difference:

    let result;
    let start1 = new Date();
    for (let i = 0; i < 1000000000; i++) {
        result = "Location Item";
    }
    let end1 = new Date();
    
    const LOCATION_ITEM = "Location Item";
    for (let i = 0; i < 1000000000; i++) {
        result = LOCATION_ITEM;
    }
    let end2 = new Date();
    
    console.log({
        withoutOptimization: end1 - start1,
        withOptimization: end2 - end1
    });

    Whenever you want to do this kind of performance comparison, write stress-testing code and you will know the answer.

    I have edited the snippet based on the discussion in the comment-section. If we store the string, then the first chunk starts to be quicker then the second. So, let’s invert the order:

    let result;
    let start1 = new Date();
    const LOCATION_ITEM = "Location Item";
    for (let i = 0; i < 1000000000; i++) {
        result = LOCATION_ITEM;
    }
    let end1 = new Date();
    
    for (let i = 0; i < 1000000000; i++) {
        result = "Location Item";
    }
    let end2 = new Date();
    
    console.log({
        withoutOptimization: end1 - start1,
        withOptimization: end2 - end1
    });

    According to my tests, the reuse of LOCATION_ITEM and passing it to result is slower if we store the string, independently of whether it’s the first or the second example.

    Login or Signup to reply.
  2. If you were actually creating a new object in your loop, that would make a difference, but the string literal "Location Item" would already be treated as a constant by any sane JavaScript engine implementation. Strings (not to be confused with String Objects) are immutable, and strictly compared by value, so it would make no sense for the engine to reconstruct the string each time this function is called. See this and this for more details.

    So moving that out to a separate variable isn’t going to give you better performance. In theory, it could yield slightly worse performance because the lambda function would need to "close over" that variable. JIT compilation may be smart enough to recognize that particular variable can only ever have one value and optimize it away, though.

    In any case it’s highly unlikely to matter. Unless this is a point in code that gets hit insanely often, you’ve probably spent more time reading this answer than the combined difference of CPU time for the entire lifetime of your application. If this were a really critical performance point in your application, you’d probably want to optimize it further by using loops rather than Array.forEach or maybe even compiling it into WASM or something. But "Premature Optimization is the root of all evil" so I wouldn’t worry about these things unless your testing shows that this loop is the source of a noticeable performance issue.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search