@arcgis/core
Version:
ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API
3 lines (2 loc) • 5.41 kB
JavaScript
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */
import has from"./has.js";const t=-3,s=t-1,e=!!has("esri-tests-disable-gpu-memory-measurements");class i{constructor(t,s,e,i=0){this.name=t,this._storage=s,this.removeFunc=e,this._defaultPriority=i,this.id=`${o++}${n}`,this.size=0,this._hit=0,this._miss=0,this._storage.register(this)}destroy(){this._storage.deregister(this),this._storage=r}get hitRate(){return this._hit/(this._hit+this._miss)}get storageSize(){return this._storage.size}getSize(t){return this._storage.getSize(this,t)}set maxSize(t){this._storage.setMaxSize(this,t)}resetHitRate(){this._hit=this._miss=0}put(t,s,e=this._defaultPriority){this._storage.put(this,t,s,s.usedMemory,e)}pop(t){const s=this._storage.pop(this,t);return void 0===s?++this._miss:++this._hit,s}get(t){const s=this._storage.get(this,t);return void 0===s?++this._miss:++this._hit,s}peek(t){return this._storage.peek(this,t)}updateSize(t){this._storage.updateSize(this,t)}clear(){this._storage.clear(this)}clearAll(){this._storage.clearAll()}*[Symbol.iterator](){yield*this._storage.values(this)}get performanceInfo(){return this._storage.performanceInfo}resetStats(){this._storage.resetStats()}}class h{get size(){return this._size}constructor(t=10485760){this._maxSize=t,this._db=new Map,this._size=0,this._hit=0,this._miss=0,this._users=new Map,this._sizeLimits=new Map}destroy(){this.clearAll(),this._sizeLimits.clear(),this._users.clear(),this._db.clear()}register(t){this._users.set(t.id.slice(0,-1),t)}deregister(t){this.clear(t),this._sizeLimits.delete(t),this._users.delete(t.id.slice(0,-1))}get maxSize(){return this._maxSize}set maxSize(t){this._maxSize=Math.max(t,-1),this._checkSize()}getSize(t,s){const e=this._db.get(t.id+s);return e?.size??0}put(i,h,r,o,n){h=i.id+h;const a=this._db.get(h);if(a&&(this._size-=a.size,i.size-=a.size,this._db.delete(h),a.entry!==r&&this._notifyRemove(h,a.entry,a.size,0)),o>this._maxSize)return void this._notifyRemove(h,r,o,0);if(void 0===r)return void console.warn("Refusing to cache undefined entry ");if(!o||o<0)return e||console.warn(`Refusing to cache entry with size ${o} for key ${h}`),void this._notifyRemove(h,r,0,0);const c=1+Math.max(n,s)-t;this._db.set(h,new _(r,o,c)),this._size+=o,i.size+=o,this._checkSize()}updateSize(t,s){s=t.id+s;const e=this._db.get(s);if(!e)return;this._size-=e.size,t.size-=e.size;let i=e.entry.usedMemory;for(;i>this._maxSize;){const t=this._notifyRemove(s,e.entry,i,1);if(!(null!=t&&t>0))return void this._db.delete(s);i=t}e.size=i,this._size+=i,t.size+=i,this._checkSize()}pop(t,s){s=t.id+s;const e=this._db.get(s);if(e)return this._size-=e.size,t.size-=e.size,this._db.delete(s),++this._hit,e.entry;++this._miss}get(t,s){s=t.id+s;const e=this._db.get(s);if(void 0!==e)return this._db.delete(s),e.lives=e.lifetime,this._db.set(s,e),++this._hit,e.entry;++this._miss}peek(t,s){const e=this._db.get(t.id+s);return e?++this._hit:++this._miss,e?.entry}get performanceInfo(){const s={Size:Math.round(this._size/1048576)+"/"+Math.round(this._maxSize/1048576)+"MB","Hit rate":Math.round(100*this._getHitRate())+"%",Entries:this._db.size.toString()},e={},i=new Array;this._db.forEach((t,s)=>{const h=t.lifetime;i[h]=(i[h]||0)+t.size,this._users.forEach(i=>{const{id:h,name:r}=i;if(s.startsWith(h)){const s=e[r]||0;e[r]=s+t.size}})});const h={};this._users.forEach(t=>{const s=t.name;if("hitRate"in t&&"number"==typeof t.hitRate&&!isNaN(t.hitRate)&&t.hitRate>0){const i=e[s]||0;e[s]=i,h[s]=Math.round(100*t.hitRate)+"%"}else h[s]="0%"});const r=Object.keys(e);r.sort((t,s)=>e[s]-e[t]),r.forEach(t=>s[t]=Math.round(e[t]/2**20)+"MB / "+h[t]);for(let o=i.length-1;o>=0;--o){const e=i[o];e&&(s["Priority "+(o+t-1)]=Math.round(e/this._size*100)+"%")}return s}resetStats(){this._hit=this._miss=0,this._users.forEach(t=>t.resetHitRate())}clear(t){const s=t.id;this._db.forEach((t,e)=>{e.startsWith(s)&&(this._size-=t.size,this._db.delete(e),this._notifyRemove(e,t.entry,t.size,0))}),t.size=0}clearAll(){this._db.forEach((t,s)=>this._notifyRemove(s,t.entry,t.size,0)),this._users.forEach(t=>t.size=0),this._size=0,this._db.clear()}*values(t){for(const[s,e]of this._db)s.startsWith(t.id)&&(yield e.entry)}_getHitRate(){return this._hit/(this._hit+this._miss)}_notifyRemove(t,s,e,i){const h=this._users.get(t.split(n)[0])?.removeFunc,r=h?.(s,i,e);return"number"==typeof r?r:null}_checkSize(){this._sizeLimits.forEach((t,s)=>this._checkSizeLimits(t,s)),this._checkSizeLimits(this.maxSize)}setMaxSize(t,s){null==s||s<=0?this._sizeLimits.delete(t):this._sizeLimits.set(t,s)}_checkSizeLimits(t,s){const e=s??this;if(e.size<=t)return;const i=s?.id;let h=!0;for(;h;){h=!1;for(const[r,o]of this._db)if(0===o.lifetime&&(!i||r.startsWith(i))){const i=s??this._users.get(r.split(n)[0]);if(this._purgeItem(r,o,i),e.size<=.9*t)return;h||=this._db.has(r)}}for(const[r,o]of this._db)if(!i||r.startsWith(i)){const i=s??this._users.get(r.split(n)[0]);if(this._purgeItem(r,o,i),e.size<=.9*t)return}}_purgeItem(t,s,e){if(this._db.delete(t),s.lives<=1){this._size-=s.size,e&&(e.size-=s.size);const i=this._notifyRemove(t,s.entry,s.size,1);null!=i&&i>0&&(this._size+=i,e&&(e.size+=i),s.lives=s.lifetime,s.size=i,this._db.set(t,s))}else--s.lives,this._db.set(t,s)}}const r=new h(0);let o=0;class _{constructor(t,s,e){this.entry=t,this.size=s,this.lifetime=e,this.lives=e}}const n=":";export{i as MemCache,h as MemCacheStorage,t as MinPriority,s as NoPriority};