React中的缓冲池技术

什么是缓冲池

对于一些创建、销毁开销比较大的对象,或者出于减少频繁申请内存的操作,一般都会设置一个对象缓冲池,尽可能的复用已经有的对象。常见的如数据库缓冲池,游戏中一些反复创建的对象,一般也会设计一个缓冲池。

为什么要用缓冲池

在react中,也用到了这种技术,比如React的AbstractEvent,事件一般会频繁创建,为了提升性能,就使用了缓冲池。当一个事件用完之后,如果缓冲池有空间,它就会被放置回去,等待下一次使用,当然,下一次使用时,会更新它的属性信息,更新内存比申请新内存要快,因此缓冲池会有效的提升性能。

实现细节

关于缓冲池的实现,都在src/utils/PooledClass.js中。调用addPoolingTo(copyConstruct, pooler)方法,就可以给一个类添加pool支持。缓冲池的大小,可以通过poolSize来设置,默认是10,可以根据需求调整,例如AbstractEvent的缓冲池大小就设置成了20;同时,如果这个类有一个名为destructor的方法,则会在释放时被调用,一般用来清除对象的属性值,以便下次从缓冲池中取出时,没有前一次的数据。

在addPoolingTo中,会给目标类添加一个instancePool属性,该属性为一个数组,用来存储创建好的实例。当instancePool为空时,直接新建一个实例;否则从缓冲池中取出一个实例(pop最后一个),然后更新这个实例的值。

PooledClass里,实现了针对1个参数、2个参数、5个参数的不同情况下新建实例的情况,有点好奇,为啥不稍微再包装一下,让任意数量的参数都能够工作呢?

原来的函数是这样写的:


var oneArgumentPooler = function(copyFieldsFrom) {
  var Klass = this;
  if (Klass.instancePool.length) {
    var instance = Klass.instancePool.pop();
    Klass.call(instance, copyFieldsFrom);
    return instance;
  } else {
    return new Klass(copyFieldsFrom);
  }
};

var twoArgumentPooler = function(a1, a2) {
  var Klass = this;
  if (Klass.instancePool.length) {
    var instance = Klass.instancePool.pop();
    Klass.call(instance, a1, a2);
    return instance;
  } else {
    return new Klass(a1, a2);
  }
};

var fiveArgumentPooler = function(a1, a2, a3, a4, a5) {
  var Klass = this;
  if (Klass.instancePool.length) {
    var instance = Klass.instancePool.pop();
    Klass.call(instance, a1, a2, a3, a4, a5);
    return instance;
  } else {
    return new Klass(a1, a2, a3, a4, a5);
  }
};

我觉得可以写成:


var anyArgumentPooler = function(){
  var Klass = this;
  var instance = null;
  if(Klass.instancePool.length){
     instance = Klass.instancePool.pop();
  }else{
     let temp = function(){};
     temp.prototype = klass.prototype;
     instance = new temp();
   }
  Klass.apply(instance, arguments);
  return instance;
};

这样任意数量的参数都可以一样处理吧。

Show Comments

Get the latest posts delivered right to your inbox.