国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

解讀 React 的 pooledClass.js

Chiclaim / 1809人閱讀

摘要:對(duì)象池類的成員應(yīng)該都是靜態(tài)的。事實(shí)上,由于對(duì)象池技術(shù)將對(duì)象限制在一定的數(shù)量,也有效地減少了應(yīng)用程序內(nèi)存上的開(kāi)銷。對(duì)生成時(shí)開(kāi)銷不大的對(duì)象進(jìn)行池化,反而可能會(huì)出現(xiàn)維護(hù)對(duì)象池的開(kāi)銷大于生成新對(duì)象的開(kāi)銷,從而使性能降低的情況。

前言

在學(xué)習(xí) React 事件系統(tǒng)的時(shí)候,在事件分發(fā)的 dispatch方法發(fā)現(xiàn)了調(diào)用了一個(gè) pooledClass 方法,一時(shí)半會(huì)沒(méi)看明白這個(gè)方法的用意。

我們先看一下是怎么用的:

// step1
function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {
  this.topLevelType = topLevelType;
  this.nativeEvent = nativeEvent;
  this.ancestors = [];
}
Object.assign(TopLevelCallbackBookKeeping.prototype, {
  destructor: function() {
    this.topLevelType = null;
    this.nativeEvent = null;
    this.ancestors.length = 0;
  },
});
PooledClass.addPoolingTo(
  TopLevelCallbackBookKeeping,
  PooledClass.twoArgumentPooler
);

// step2
var bookKeeping = TopLevelCallbackBookKeeping.getPooled(
  topLevelType,
  nativeEvent
);
// bookKeeping 是 TopLevelCallbackBookKeeping 的實(shí)例
try {
  // Event queue being processed in the same cycle allows
  // `preventDefault`.
  ReactUpdates.batchedUpdates(handleTopLevelImpl, bookKeeping);
} finally {
  //釋放
  TopLevelCallbackBookKeeping.release(bookKeeping);
}

那么這里為什么不直接 new 一個(gè) TopLevelCallbackBookKeeping, 而要通過(guò)這個(gè) PooledClass 來(lái)返回 TopLevelCallbackBookKeeping 的實(shí)例呢

對(duì)象池
單例模式是限制了一個(gè)類只能有一個(gè)實(shí)例,對(duì)象池模式則是限制一個(gè)類實(shí)例的個(gè)數(shù)。對(duì)象池類就像是一個(gè)對(duì)象管理員,它以Static列表(也就是裝對(duì)象的池子)的形式存存儲(chǔ)某個(gè)實(shí)例數(shù)受限的類的實(shí)例,每一個(gè)實(shí)例還要加一個(gè)標(biāo)記,標(biāo)記該實(shí)例是否被占用。當(dāng)類初始化的時(shí)候,這個(gè)對(duì)象池就被初始化了,實(shí)例就被創(chuàng)建出來(lái)。然后,用戶可以向這個(gè)類索取實(shí)例,如果池中所有的實(shí)例都已經(jīng)被占用了,那么拋出異常。用戶用完以后,還要把實(shí)例“還”回來(lái),即釋放占用。對(duì)象池類的成員應(yīng)該都是靜態(tài)的。用戶也不應(yīng)該能訪問(wèn)池子里裝著的對(duì)象的構(gòu)造函數(shù),以防用戶繞開(kāi)對(duì)象池創(chuàng)建實(shí)例。書(shū)上說(shuō)這個(gè)模式會(huì)用在數(shù)據(jù)庫(kù)連接的管理上。比如,每個(gè)用戶的連接數(shù)是有限的,這樣每個(gè)連接就是一個(gè)池子里的一個(gè)對(duì)象,“連接池”類就可以控制連接數(shù)了。
如果說(shuō)每次觸發(fā) dispatch 的時(shí)候都用 new TopLevelCallbackBookKeeping 來(lái) new 一個(gè)對(duì)象,那么當(dāng)觸發(fā)很多次 dispatch 的時(shí)候,就會(huì)導(dǎo)致生成多個(gè)對(duì)象無(wú)法銷毀(多個(gè)bookKeeping的引用次數(shù)一直為1),導(dǎo)致內(nèi)存溢出。
對(duì)象池技術(shù)的基本原理

對(duì)象池技術(shù)基本原理的核心有兩點(diǎn):緩存和共享,即對(duì)于那些被頻繁使用的對(duì)象,在使用完后,不立即將它們釋放,而是將它們緩存起來(lái),以供后續(xù)的應(yīng)用程序重復(fù)使用,從而減少創(chuàng)建對(duì)象和釋放對(duì)象的次數(shù),進(jìn)而改善應(yīng)用程序的性能。事實(shí)上,由于對(duì)象池技術(shù)將對(duì)象限制在一定的數(shù)量,也有效地減少了應(yīng)用程序內(nèi)存上的開(kāi)銷。

對(duì)象池使用的基本思路是

將用過(guò)的對(duì)象保存起來(lái),等下一次需要這種對(duì)象的時(shí)候,再拿出來(lái)重復(fù)使用,從而在一定程度上減少頻繁創(chuàng)建對(duì)象所造成的開(kāi)銷。React 的 pooledClass.js 就是一個(gè)例子:

var invariant = require("invariant");

/**
 * Static poolers. Several custom versions for each potential number of
 * arguments. A completely generic pooler is easy to implement, but would
 * require accessing the `arguments` object. In each of these, `this` refers to
 * the Class itself, not an instance. If any others are needed, simply add them
 * here, or in their own files.
 */
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 standardReleaser = function(instance) {
  var Klass = this;
  invariant(
    instance instanceof Klass,
    "Trying to release an instance into a pool of a different type."
  );
  instance.destructor();
  if (Klass.instancePool.length < Klass.poolSize) {
    Klass.instancePool.push(instance);
  }
};

var DEFAULT_POOL_SIZE = 10;
var DEFAULT_POOLER = oneArgumentPooler;

/**
 * Augments `CopyConstructor` to be a poolable class, augmenting only the class
 * itself (statically) not adding any prototypical fields. Any CopyConstructor
 * you give this may have a `poolSize` property, and will look for a
 * prototypical `destructor` on instances (optional).
 *
 * @param {Function} CopyConstructor Constructor that can be used to reset.
 * @param {Function} pooler Customizable pooler.
 */
var addPoolingTo = function(CopyConstructor, pooler) {
  var NewKlass = CopyConstructor;
  NewKlass.instancePool = [];
  NewKlass.getPooled = pooler || DEFAULT_POOLER;
  if (!NewKlass.poolSize) {
    NewKlass.poolSize = DEFAULT_POOL_SIZE;
  }
  NewKlass.release = standardReleaser;
  return NewKlass;
};

var PooledClass = {
  addPoolingTo: addPoolingTo,
  oneArgumentPooler: oneArgumentPooler,
  twoArgumentPooler: twoArgumentPooler,
  threeArgumentPooler: threeArgumentPooler,
  fourArgumentPooler: fourArgumentPooler,
  fiveArgumentPooler: fiveArgumentPooler,
};

module.exports = PooledClass;

具體分為三步

addPoolingTo 添加對(duì)象到池子

調(diào)用的時(shí)候發(fā)現(xiàn)是否有緩存,有緩存就pop()出來(lái)用, 沒(méi)有緩存就新增一個(gè)

使用完成之后,釋放對(duì)象,緩存進(jìn)去

說(shuō)的再簡(jiǎn)單一點(diǎn)就是

創(chuàng)建對(duì)象 addPoolingTo()

借取對(duì)象 getPooled()

歸還對(duì)象 release()

總結(jié)

并非所有對(duì)象都適合拿來(lái)池化――因?yàn)榫S護(hù)對(duì)象池也要造成一定開(kāi)銷。對(duì)生成時(shí)開(kāi)銷不大的對(duì)象進(jìn)行池化,反而可能會(huì)出現(xiàn)“維護(hù)對(duì)象池的開(kāi)銷”大于“生成新對(duì)象的開(kāi)銷”,從而使性能降低的情況。但是對(duì)于生成時(shí)開(kāi)銷可觀的對(duì)象,池化技術(shù)就是提高性能的有效策略了。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/97921.html

相關(guān)文章

  • 開(kāi)發(fā)工具心得:如何 10 倍提高你 Webpack 構(gòu)建效率

    摘要:在項(xiàng)目架構(gòu)中這兩個(gè)東西基本成為了標(biāo)配,但的模塊必須在使用前經(jīng)過(guò)的構(gòu)建后文稱為才能在瀏覽器端使用,而每次修改也都需要重新構(gòu)建后文稱為才能生效,如何提高的構(gòu)建效率成為了提高開(kāi)發(fā)效率的關(guān)鍵之一。 0. 前言 showImg(https://segmentfault.com/img/remote/1460000005770045); 圖1:ES6 + Webpack + React + Bab...

    用戶83 評(píng)論0 收藏0
  • React 源碼深度解讀(四):首次自定義組件渲染 - Part 1

    摘要:本篇開(kāi)始介紹自定義組件是如何渲染的。組件將自定義組件命名為,結(jié)構(gòu)如下經(jīng)過(guò)編譯后,生成如下代碼構(gòu)建頂層包裝組件跟普通元素渲染一樣,第一步先會(huì)執(zhí)行創(chuàng)建為的。調(diào)用順序已在代碼中注釋。先看圖,這部分內(nèi)容將在下回分解 前言 React 是一個(gè)十分龐大的庫(kù),由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)非常深,閱讀其源碼是一個(gè)非...

    Warren 評(píng)論0 收藏0
  • React 源碼深度解讀(三):首次 DOM 元素渲染 - Part 3

    摘要:在學(xué)習(xí)源碼的過(guò)程中,給我?guī)椭畲蟮木褪沁@個(gè)系列文章,于是決定基于這個(gè)系列文章談一下自己的理解。到此為止,首次渲染就完成啦總結(jié)從啟動(dòng)到元素渲染到頁(yè)面,并不像看起來(lái)這么簡(jiǎn)單,中間經(jīng)歷了復(fù)雜的層級(jí)調(diào)用。 前言 React 是一個(gè)十分龐大的庫(kù),由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)非常深,閱讀其源碼是一個(gè)非常艱辛的過(guò)...

    U2FsdGVkX1x 評(píng)論0 收藏0
  • React 源碼深度解讀(六):依賴注入

    摘要:依賴注入和控制反轉(zhuǎn),這兩個(gè)詞經(jīng)常一起出現(xiàn)。一句話表述他們之間的關(guān)系依賴注入是控制反轉(zhuǎn)的一種實(shí)現(xiàn)方式。而兩者有大量的代碼都是可以共享的,這就是依賴注入的使用場(chǎng)景了。下一步就是創(chuàng)建具體的依賴內(nèi)容,然后注入到需要的地方這里的等于這個(gè)對(duì)象。 前言 React 是一個(gè)十分龐大的庫(kù),由于要同時(shí)考慮 ReactDom 和 ReactNative ,還有服務(wù)器渲染等,導(dǎo)致其代碼抽象化程度很高,嵌套層級(jí)...

    glumes 評(píng)論0 收藏0
  • React 源碼深度解讀(一):首次DOM元素渲染 - Part 1

    摘要:調(diào)用棧是這樣的這里生成的我們將其命名為,它將作為參數(shù)傳入到。整個(gè)的調(diào)用棧是這樣的組件間的層級(jí)結(jié)構(gòu)是這樣的到此為止,頂層對(duì)象已經(jīng)構(gòu)造完畢,下一步就是調(diào)用來(lái)自的方法,進(jìn)行頁(yè)面的渲染了。通過(guò)表達(dá)的結(jié)構(gòu)最終會(huì)轉(zhuǎn)化為一個(gè)純對(duì)象,用于下一步的渲染。 歡迎關(guān)注我的公眾號(hào)睿Talk,獲取我最新的文章:showImg(https://segmentfault.com/img/bVbmYjo); 一、前言...

    daydream 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<