-
Notifications
You must be signed in to change notification settings - Fork 12.9k
Minification: Create local variable for prototype during class declaration #16469
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
Conversation
9dc83df
to
4e794c7
Compare
Isn't this worse after compression? Do you have some numbers? |
Hey @dmichon-msft, I think @alfaproject is correct. When using gzip compression, my understanding is that you end up with a table referencing these repeated segments anyway. Now, you have the same table lookup with additional code for the prototype alias that's inserted. aving tried the given samples out on this page it looks like this change is less efficient. Do you have concrete numbers indicating otherwise? |
@alfaproject @DanielRosenwasser So, for a single, small class, this change results in slightly larger files after gzip. All following analytics are conducted by assuming that the minifier will perform optimum renaming of variables for maximum compressibility, then passing them through this page that Daniel linked. Single, small class: var A = (function () {
function A() {
}
A.prototype.a = function () { };
A.prototype.b = function () { };
Object.defineProperty(A.prototype, "c", {
get: function () { return 1; },
enumerable: true,
configurable: true
});
}()); Result: 273 bytes before, 163 bytes after gzip var A = (function () {
function A() {
}
var a = A.prototype;
a.a = function () { };
a.b = function () { };
Object.defineProperty(a, "c", {
get: function () { return 1; },
enumerable: true,
configurable: true
});
}()); Result: 268 bytes before, 168 bytes after gzip If we add a couple more classes: var A = (function () {
function A() {
}
A.prototype.a = function () { };
A.prototype.b = function () { };
Object.defineProperty(A.prototype, "c", {
get: function () { return 1; },
enumerable: true,
configurable: true
});
}());
var B = (function () {
function A() {
}
A.prototype.c = function () { };
A.prototype.d = function () { };
A.prototype.e = function () { };
A.prototype.f = function () { };
}());
var C = (function () {
function A() {
}
A.prototype.g = function () { };
A.prototype.h = function () { };
A.prototype.i = function () { };
A.prototype.j = function () { };
A.prototype.k = function () { };
}()); Result: 716 bytes before, 206 bytes after gzip var A = (function () {
function A() {
}
var a = A.prototype;
a.a = function () { };
a.b = function () { };
Object.defineProperty(a, "c", {
get: function () { return 1; },
enumerable: true,
configurable: true
});
}());
var B = (function () {
function A() {
}
var a = A.prototype;
a.c = function () { };
a.d = function () { };
a.e = function () { };
a.f = function () { };
}());
var C = (function () {
function A() {
}
var a = A.prototype;
a.g = function () { };
a.h = function () { };
a.i = function () { };
a.j = function () { };
a.k = function () { };
}()); Results: 671 bytes before, 206 bytes after gzip Adding more classes or members from this point gradually leans in favor of the change, though the delta is relatively small. If I change the starting assumption about the minifier performing optimal variable renaming, then things get a bit stranger. I attempted to invoke the modified compiler against a much larger internal project, but due to some difficulties my numbers for the modified compiler include upstream files still built using the old compiler, and more local files build with the modified version. Nonetheless, some partial numbers for some real world projects (all post gzip):
Edit: it should be noted that in all tested scenarios the pre-gzip size is smaller with the modification. |
So, to sum up, gzip is pretty fantastic at compressing away |
This should also result in a small runtime performance improvement by avoiding the need to lookup the prototype property repeatedly. The engine's optimizer might be able to help once it warms up, but this code likely all runs during application startup while you're inside the interpreter. |
Thanks for your contribution. This PR has not been updated in a while and cannot be automatically merged at the time being. For housekeeping purposes we are closing stale PRs. If you'd still like to continue working on this PR, please leave a message and one of the maintainers can reopen it. |
Can we revive this PR anyone? |
Creates a local variable storing a class's prototype to support better minification of class declarations when emitting for ES5 and below.
Example
Source
Old ES5 emit
New ES5 Emit
Fixes #9638