admin管理员组

文章数量:1404603

I have the following 3 different ways of creating an object instance.

I was wondering which of one of these is faster, takes less memory and why?

//Option 1        
export interface Animal1 {
    name: string;
    color: string;
    isHungry: boolean;
}
let animal: Animal1 = {
    name: 'cat',
    color: 'brown',
    isHungry: true
};

//Option 2   
export class Animal2 {
    name: string;
    color: string;
    isHungry: boolean;
}
let animal2: Animal2 = new Animal2();
animal2.name = 'cat';
animal2.color = 'brown';
animal2.isHungry = true;
     
//Option 3   
export class Animal3 {
    constructor(public name:string, public color:string, public isHungry:boolean) {}
}
let animal3 = new Animal3('cat', 'brown', true);

As of coding style and maintenance I prefer option 1 with builder classes in unit testing. Option 3 is the least favourite as it's:

  • Difficult to create an object easily, you have to set all properties
  • Difficult to maintain, every time a new property is added you need to update every single instance creation
  • Error prone, when the number of properties with the same type is high, e.g string, string, string. You may set the wrong property.

Is there any performance/memory difference between these three?

I have the following 3 different ways of creating an object instance.

I was wondering which of one of these is faster, takes less memory and why?

//Option 1        
export interface Animal1 {
    name: string;
    color: string;
    isHungry: boolean;
}
let animal: Animal1 = {
    name: 'cat',
    color: 'brown',
    isHungry: true
};

//Option 2   
export class Animal2 {
    name: string;
    color: string;
    isHungry: boolean;
}
let animal2: Animal2 = new Animal2();
animal2.name = 'cat';
animal2.color = 'brown';
animal2.isHungry = true;
     
//Option 3   
export class Animal3 {
    constructor(public name:string, public color:string, public isHungry:boolean) {}
}
let animal3 = new Animal3('cat', 'brown', true);

As of coding style and maintenance I prefer option 1 with builder classes in unit testing. Option 3 is the least favourite as it's:

  • Difficult to create an object easily, you have to set all properties
  • Difficult to maintain, every time a new property is added you need to update every single instance creation
  • Error prone, when the number of properties with the same type is high, e.g string, string, string. You may set the wrong property.

Is there any performance/memory difference between these three?

Share Improve this question edited Jun 15, 2021 at 23:18 Inigo 15.2k5 gold badges50 silver badges82 bronze badges asked Aug 22, 2018 at 19:30 shivashiva 7641 gold badge12 silver badges26 bronze badges 4
  • I don't have an answer to the performance question, but option 3 can be written more concisely using parameter properties: constructor(public name: string, public color: string, public isHungry: boolean) {}. – Matt McCutchen Commented Aug 22, 2018 at 19:39
  • The first way should be the fastest as it does not invoke a function call. Remember that TypeScript is transpiled to JavaScript and new actually calls a function in which the function context this is set to a new empty object. – Krisztián Balla Commented Aug 22, 2018 at 19:42
  • @MattMcCutchen true, it's better way of doing it. I copy and paste the option 2 and forgot to change it. – shiva Commented Aug 22, 2018 at 19:43
  • @MattMcCutchen I updated it, thanks. – shiva Commented Aug 22, 2018 at 19:58
Add a ment  | 

2 Answers 2

Reset to default 4

It is not possible to say, in a general sense, which is “fastest”.

Object instance creation is highly optimized in JavaScript engines. The speed will be affected by the surrounding code, the frequency with which it is run, the runtime version and many other factors.

I’m sorry this is not the answer you wanted.

In terms of memory, you can simply count the objects created by each approach - but unless you are writing a highly optimized piece of JavaScript (unlikely), this will be moot.

Typically your choice of pattern for object creation should be driven not by performance, but by non-functional requirements like the style of code agreed by the team, maintainability and API shape.

Of course, algorithms written in TS or JS can still be analysed for time and space plexity in the usual way.

The same as in JavaScript. There might be the little difference in object creation times, but the noticeable impact on overall performance of the code which uses these types. These options are not equal.

The reason is "hidden classes" JIT optimization and things JIT can do with the monomorphic code. If object members are always initialized in the same order, JIT can assign the same "hidden class" to all of the type instances and then use this information to access class members using memory offset instead of the expensive hash table lookup. When you iterate through the collection of objects having the same hidden class (or repeatedly call the function with arguments having the same hidden classes) JIT can recognize the monomorphic code and pile the specialized version of the function with excessive type checks omitted, dynamically inline method calls, and do some other magic which makes modern JS VM so fast.

So, in general, the monomorphic code is faster than the polymorphic one, and the order of properties initialization is being used by JIT to determine the "internal object type".

https://draft.li/blog/2016/12/22/javascript-engines-hidden-classes/

https://richardartoul.github.io/jekyll/update/2015/04/26/hidden-classes.html

The easiest and safest way to enable these optimizations is to use the class and make sure that all class members are always initialized in the same order in its constructor which is an option 3 from your example. Option 2 is the worst as there's no guarantee that the "hidden class" will be the same for the different class instances, and JIT won't consider them having the same type.

The last but not least. There's nothing obvious about JS JIT performance. Not only JIT engines use slightly different (yet very sophisticated) optimization strategies, but they evolve at a time which makes the majority of articles about JIT internals obsolete in quite a short period of time. However, "hidden classes" or similar optimizations allowing JIT to take advantage of the monomorphic code are fundamental for the JS JIT performance.

Anyway, don't guess about performance and don't believe in seemingly obvious things others say. Measure it.

本文标签: javascriptWhich way of object instance creation is the fastest in TypeScriptStack Overflow