-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Revised name generation #2455
Revised name generation #2455
Conversation
I'm concerned about the debugging impact. Also about this bit: "Perf-wise this approach is preferable since to determine if the name is truly unique we need to do just 3 map lookups". I'd like to know more accurately what the perf impact is of making better names that work well in most current debuggers. While i agree it will be more expensive, i have no sense of if that expense will be unacceptable. Or, in other words, i think we should be optimizing for the end user experience with our language (including hte debugging experience), not just the raw performance of our compiler. A fast compiler isn't very helpful if it generates code that you don't want. Another option is to use the --sourceMap flag as an indicator to us as to what sort of names to generate. If you use --sourceMap, then you're telling us you want to be able to debug this usign the original TS. In that case, we generate names that are as good as possible. If you don't have --sourceMap, then you'd only be debugging with the JS. And, in that case, the names just have to be ok. So we can be faster in the case where you don't use --sourceMap, and slower if you want great debugging. |
In order to test the impact of name generation to the emit time we need codebase that heavily uses lexical declarations - I've used TypeScript compiler as a guinea pig.
Extra name check was done by threading |
@vladima Great! Thanks for the data. I'd def still like to know the cost of:
I can work with you on this early next week to help collect more data, so that this isn't all on you to do the investigation. And, actually, if you make a branch for the perf tests you've been doing (i.e. the area where you got the 2.74s time), then i can try out the second approach above soon. Or, you can just try merging in the containerMadness branch into your own branch to try it out. Either way works for me. Thanks! |
@vladima I assume we only rename |
@ahejlsberg: Existing implementation renames declare function use(a: any);
var x;
{
let x;
use(x);
function foo() {
var _x; // name that will collide with generated name
use(x); // will use '_x' from nested scope
}
} Current ideas how to deal with this issue:
|
if (node.name.kind === SyntaxKind.Identifier) { | ||
let name = node.name.text; | ||
// Use module/enum name itself if it is unique, otherwise make a unique variation | ||
return assignGeneratedName(node, isUniqueLocalName(name, node) ? name : makeUniqueName(name)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why does module or enum do isUniqueLocalName, but everybody else doesn't?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this code was moved from the checker without modifications
@vladima Regarding which approach to take, as long as we only rename when we absolutely have to, I think it is fine to just pick globally unique names (i.e. approach #1). There's really not a big qualitative difference between a locally unique |
I agree. We should avoid renames when possible. But, when renames are absolutely necessary, the only thing i care about is that the final name have some indication about where it came from. |
Okay, so it sounds like we really only care about how many / which declarations get renamed, not how big the suffix number is at the end. That is fair, but if we compare the different approaches @vladima outlined, will the current PR actually rename more things than the other two approaches? That is the impression I got, but maybe I am wrong about that. If the conditions for uniqueness of the variable's original name are the same, then approach 1 doesn't seem much worse for debugging than approach 2. The same names will be unfaithful to the source in both approaches. There is one exception. Consider the user who is debugging and tries to type |
closing since this is covered by #2471 |
This PR is a proposal to consolidate different ways to generate temp names that we have in the compiler.
It moves name generation for modules from the checker into the emitter (so pre-pass is not needed) and names can be generated on-demand using two functions:
makeUniqueName
- creates a name that does not exist in global scope and unique to current file. This name will never be generated in the future nor by makeUniqueName neither bymakeTempVariable
makeTempVariable
- creates a name that does not exists anywhere higher in the scope (in user code) and unique among generated names in current scope. The same name however can be generated by calls tomakeTempVariable
above or below in the scope and it is up to the user to protect yourself from this fact.Perf-wise this approach is preferable since to determine if the name is truly unique we need to do just 3 map lookups: globals, identifiers in current file, generated names in current file. However it comes with a cost of degrading debugging experience: i.e. in compiler codebase some names that were used quite frequently, i.e.
result
were transformed into something like_result_101
.@ahejlsberg, @JsonFreeman: feedback is welcomed