IsolateManager.js 4.1 KB

1234567891011121314151617181920212223242526272829303132333435363738
  1. export default class IsolateManager extends Common.Object{constructor(){super();console.assert(!SDK.isolateManager,'Use SDK.isolateManager singleton.');this._isolates=new Map();this._isolateIdByModel=new Map();this._observers=new Set();SDK.targetManager.observeModels(SDK.RuntimeModel,this);this._pollId=0;}
  2. observeIsolates(observer){if(this._observers.has(observer)){throw new Error('Observer can only be registered once');}
  3. if(!this._observers.size){this._poll();}
  4. this._observers.add(observer);for(const isolate of this._isolates.values()){observer.isolateAdded(isolate);}}
  5. unobserveIsolates(observer){this._observers.delete(observer);if(!this._observers.size){++this._pollId;}}
  6. modelAdded(model){this._modelAdded(model);}
  7. async _modelAdded(model){this._isolateIdByModel.set(model,null);const isolateId=await model.isolateId();if(!this._isolateIdByModel.has(model)){return;}
  8. if(!isolateId){this._isolateIdByModel.delete(model);return;}
  9. this._isolateIdByModel.set(model,isolateId);let isolate=this._isolates.get(isolateId);if(!isolate){isolate=new Isolate(isolateId);this._isolates.set(isolateId,isolate);}
  10. isolate._models.add(model);if(isolate._models.size===1){for(const observer of this._observers){observer.isolateAdded(isolate);}}else{for(const observer of this._observers){observer.isolateChanged(isolate);}}}
  11. modelRemoved(model){const isolateId=this._isolateIdByModel.get(model);this._isolateIdByModel.delete(model);if(!isolateId){return;}
  12. const isolate=this._isolates.get(isolateId);isolate._models.delete(model);if(isolate._models.size){for(const observer of this._observers){observer.isolateChanged(isolate);}
  13. return;}
  14. for(const observer of this._observers){observer.isolateRemoved(isolate);}
  15. this._isolates.delete(isolateId);}
  16. isolateByModel(model){return this._isolates.get(this._isolateIdByModel.get(model)||'')||null;}
  17. isolates(){return this._isolates.values();}
  18. async _poll(){const pollId=this._pollId;while(pollId===this._pollId){await Promise.all(Array.from(this.isolates(),isolate=>isolate._update()));await new Promise(r=>setTimeout(r,PollIntervalMs));}}}
  19. export class Observer{isolateAdded(isolate){}
  20. isolateRemoved(isolate){}
  21. isolateChanged(isolate){}}
  22. export const Events={MemoryChanged:Symbol('MemoryChanged')};export const MemoryTrendWindowMs=120e3;const PollIntervalMs=2e3;export class Isolate{constructor(id){this._id=id;this._models=new Set();this._usedHeapSize=0;const count=MemoryTrendWindowMs/PollIntervalMs;this._memoryTrend=new MemoryTrend(count);}
  23. id(){return this._id;}
  24. models(){return this._models;}
  25. runtimeModel(){return this._models.values().next().value||null;}
  26. heapProfilerModel(){const runtimeModel=this.runtimeModel();return runtimeModel&&runtimeModel.heapProfilerModel();}
  27. async _update(){const model=this.runtimeModel();const usage=model&&await model.heapUsage();if(!usage){return;}
  28. this._usedHeapSize=usage.usedSize;this._memoryTrend.add(this._usedHeapSize);SDK.isolateManager.dispatchEventToListeners(Events.MemoryChanged,this);}
  29. samplesCount(){return this._memoryTrend.count();}
  30. usedHeapSize(){return this._usedHeapSize;}
  31. usedHeapSizeGrowRate(){return this._memoryTrend.fitSlope();}}
  32. export class MemoryTrend{constructor(maxCount){this._maxCount=maxCount|0;this.reset();}
  33. reset(){this._base=Date.now();this._index=0;this._x=[];this._y=[];this._sx=0;this._sy=0;this._sxx=0;this._sxy=0;}
  34. count(){return this._x.length;}
  35. add(heapSize,timestamp){const x=typeof timestamp==='number'?timestamp:Date.now()-this._base;const y=heapSize;if(this._x.length===this._maxCount){const x0=this._x[this._index];const y0=this._y[this._index];this._sx-=x0;this._sy-=y0;this._sxx-=x0*x0;this._sxy-=x0*y0;}
  36. this._sx+=x;this._sy+=y;this._sxx+=x*x;this._sxy+=x*y;this._x[this._index]=x;this._y[this._index]=y;this._index=(this._index+1)%this._maxCount;}
  37. fitSlope(){const n=this.count();return n<2?0:(this._sxy-this._sx*this._sy/n)/(this._sxx-this._sx*this._sx/n);}}
  38. self.SDK=self.SDK||{};SDK=SDK||{};SDK.IsolateManager=IsolateManager;SDK.IsolateManager.Observer=Observer;SDK.IsolateManager.Events=Events;SDK.IsolateManager.MemoryTrendWindowMs=MemoryTrendWindowMs;SDK.IsolateManager.Isolate=Isolate;SDK.IsolateManager.MemoryTrend=MemoryTrend;SDK.isolateManager=new IsolateManager();