-
Notifications
You must be signed in to change notification settings - Fork 90
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
提供调用extend之后的可拓展性 #8
Comments
需求来源:aralejs/base#26 |
其实也不然,如果继承链比较长,extend 会调用多遍,每次 extend 都需要去 merge 之前的属性。 这就要看使用场景了,是实例化的数量还是继承链的长短。 而且我觉得 hack class 并不是一个明智的选择。 |
能否找一个真实场景测试?现在的用例有点极端。 2013/7/8 Haoliang Gao [email protected]
王保平 / 玉伯(射雕) |
只要有个固定的规则,每次调用extend 只要merge自己和parent(parent的attrs由parent及parent的parent merge而成)的attrs 就ok了,这个调用次数基本上小于实例化的数量。 hack class 当然只是为了验证这个方法的性能提升,还是希望能有更优雅的解决方案 |
用例确实极端了点,不过稍微复杂点的功能型页面,有多个 popup,overlay 之类的实例还是很正常的。更别说 validator 这种每个 item 都是一个 widget 实例的场景了。每次都在实例化的时候都去遍历一遍继承链,重复开销很严重。。 或者说换个思路,做第一次实例化的时候对attrs做个缓存,以后每次实例化的去取该缓存,也可以节省不少开销。。 |
有点奇怪了,理论上做过缓存之后,后面反复实例化某个类的时候 merge 的次数更少了,速度应该更快才是。 代码如下: var attrsCache = {};
var cid = 1;
function mergeInheritedAttrs(attrs, instance, specialProps) {
var inherited = [];
var proto = instance.constructor.prototype;
var attrCid = instance.constructor.__cid;
// 如果 constructor 存在缓存,取缓存
if (attrCid && attrsCache[attrCid]){
mergeAttrs(attrs, attrsCache[attrCid]);
return;
}
while (proto) {
// 不要拿到 prototype 上的
if (!proto.hasOwnProperty('attrs')) {
proto.attrs = {};
}
// 将 proto 上的特殊 properties 放到 proto.attrs 上,以便合并
copySpecialProps(specialProps, proto.attrs, proto);
// 为空时不添加
if (!isEmptyObject(proto.attrs)) {
inherited.unshift(proto.attrs);
}
// 向上回溯一级
proto = proto.constructor.superclass;
}
// Merge and clone default values to instance.
for (var i = 0, len = inherited.length; i < len; i++) {
mergeAttrs(attrs, normalize(inherited[i]));
}
// 缓存在 constructor 上
instance.constructor.__cid = cid;
attrsCache[cid++] = mergeAttrs({}, attrs);
} |
cache 不一定能提升性能,之前 Sea.js 里,resolveCache 我加过,但在一般场景下,会降低性能,我当初也是纳闷死了。 后来发现 cache 本身是存在开销的(存储和查询),只有当 cache 本身的开销小于节省的开销时,对性能才有提升,否则不光耗费性能,还多占用了内存。 2013/7/8 lianqin7 [email protected]
王保平 / 玉伯(射雕) |
soga,学习了。看来在这里加缓存并没有什么实质性的提升。暂时先放弃这个优化思路了。看看从别的地方去入手 |
attribute.js ,我这样改怎么样?specialProps 感觉自己用不上就直接注释了 Class.Mutators["attrs"] = function( attrs ) {
}; exports.initAttrs = function(config) { // Get all inherited attributes. // 原型链上的属性要重新合并, 不需要 normalize ,原型合并时已调用, this.attrs 会指向最近的原型链 // Merge user-specific attributes from config. // 对于有 setter 的属性,要用初始值 set 一下,以保证关联属性也一同初始化 // Convert // 将 this.attrs 上的 special properties 放回 this 上 |
需求来源于 arale/base 的性能优化:
将 attribute 的 merge 操作由 实例化时 -> 类构建时,可以提升较多的性能
可惜现在的class的extend之后没有接口能保证所有的子类构造时,都能运行同一段功能,且对其他使用者透明( 除了hack Class.create 方法 )
或者说大家有更好的解决方案?
@lifesinger @popomore @afc163
The text was updated successfully, but these errors were encountered: