Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query regarding coding paradigm used in this library. #62

Closed
simbathesailor opened this issue May 27, 2018 · 7 comments
Closed

Query regarding coding paradigm used in this library. #62

simbathesailor opened this issue May 27, 2018 · 7 comments

Comments

@simbathesailor
Copy link

simbathesailor commented May 27, 2018

Why in the code string concatenation is used to create the function? I can see, this approach is being followed in almost every file. Why shouldn't it be written as a normal function? For example like this in HookCodeFactory .

switch(this.options.type) { case "sync": return new Function(this.args(), "\"use strict\";\n" + this.header() + this.content({ onError: err => throw ${err};\n, onResult: result => return ${result};\n, onDone: () => "", rethrowIfPossible: true }));

@ooflorent
Copy link
Member

Correct me if I'm wrong but you are wondering why some closures are defined using Function and string concatenations instead of a plain function declaration or expression, right?

Well, this is for optimisation purpose. Defining functions using Function constructor is expensive. However, the code generated by tapable is monomorphic and is crafted to be executed really fast.

@simbathesailor
Copy link
Author

@ooflorent First of all thanks for replying . Well You are correct . I am asking the same. I am still not getting any idea, why using Function constructor is expensive. I can read following lines on mdn

Function objects created with the Function constructor are parsed when the function is created. This is less efficient than declaring a function with a function expression or function statement and calling it within your code because such functions are parsed with the rest of the code.

May be I am thinking other way. Could you please elaborate ?

@ooflorent
Copy link
Member

Sure! Let's consider the following functions; they are really simple hook factory implementations:

const f = (...fns) => (...args) => {
  for (const fn of fns) {
    fn(...args)
  }
}

const g = (a, b, c) => (x, y) => {
  a(x, y)
  b(x, y)
  c(x, y)
}

Both functions achieve the same thing but g is more specific. While f accepts any number of callbacks and applies any number of arguments on them, g takes 3 callbacks and calls them using 2 arguments. Because g is specialised for this use case, it will perform much better than f.

Keep in mind that tapable is used by webpack. The created hooks can hold dozens of callbacks with multiple arguments depending on the event. Specialised functions like g could not realistically be used to cover all callsites. This is the reason why hooks are generated: this way it is possible to define a specialised version where loops are unrolled to improve performances.

@simbathesailor
Copy link
Author

Oh Now I understand, basically the code which is returned is dynamic. so depending on varying number of arguments and other parameters, new functions is being created and returned. In this way, the code length will be dynamic and saves the code length in most cases.

Thanks, @ooflorent. Actually going through webpack code to learn and contribute. You can close the issue !!

@elevenpassin
Copy link

What does monomorphic mean? @ooflorent

@ooflorent
Copy link
Member

Here is a good explanation: What's up with monomorphism?

@elevenpassin
Copy link

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants