浏览代码

Merge pull request #45 from NASA-AMMOS/lru-priority-update

Add support for sorting unloaded content
Garrett Johnson 5 年之前
父节点
当前提交
e99ba35165
共有 3 个文件被更改,包括 73 次插入7 次删除
  1. 4 1
      src/base/TilesRendererBase.js
  2. 34 4
      src/utilities/LRUCache.js
  3. 35 2
      test/LRUCache.test.js

+ 4 - 1
src/base/TilesRendererBase.js

@@ -9,6 +9,9 @@ import { UNLOADED, LOADING, PARSING, LOADED, FAILED } from './constants.js';
 // TODO: See if declaring function inline improves performance
 // TODO: Make sure active state works as expected
 
+// Function for sorting the evicted LRU items. We should evict the shallowest depth first.
+const lruSort = ( a, b ) => a.__depth - b.__depth;
+
 export class TilesRendererBase {
 
 	get rootTileSet() {
@@ -104,7 +107,7 @@ export class TilesRendererBase {
 		toggleTiles( root, this );
 
 		// TODO: We may want to add this function in the requestTileContents function
-		lruCache.scheduleUnload( null );
+		lruCache.scheduleUnload( lruSort );
 
 	}
 

+ 34 - 4
src/utilities/LRUCache.js

@@ -107,7 +107,7 @@ class LRUCache {
 
 	// TODO: this should be renamed because it's not necessarily unloading all unused content
 	// Maybe call it "cleanup" or "unloadToMinSize"
-	unloadUnusedContent( prioritySortCb ) {
+	unloadUnusedContent( prioritySortCb = null ) {
 
 		const unloadPercent = this.unloadPercent;
 		const targetSize = this.minSize;
@@ -120,9 +120,39 @@ class LRUCache {
 
 		if ( excess > 0 && unused > 0 ) {
 
-			// TODO: sort by priority
+			if ( prioritySortCb ) {
 
-			let nodesToUnload = Math.min( targetSize * unloadPercent, unused );
+				// used items should be at the end of the array
+				itemList.sort( ( a, b ) => {
+
+					const usedA = usedSet.has( a );
+					const usedB = usedSet.has( b );
+					if ( usedA && usedB ) {
+
+						// If they're both used then don't bother moving them
+						return 0;
+
+					} else if ( ! usedA && ! usedB ) {
+
+						// Use the sort function otherwise
+						return prioritySortCb( a, b );
+
+					} else {
+
+						// If one is used and the other is not move the used one towards the end of the array
+						return usedA ? 1 : - 1;
+
+					}
+
+				} );
+
+			}
+
+			// address corner cases where the minSize might be zero or smaller than maxSize - minSize,
+			// which would result in a very small or no items being unloaded.
+			const unusedExcess = Math.min( excess, unused );
+			const maxUnload = Math.max( targetSize * unloadPercent, unusedExcess * unloadPercent );
+			let nodesToUnload = Math.min( maxUnload, unused );
 			nodesToUnload = Math.ceil( nodesToUnload );
 
 			const removedItems = itemList.splice( 0, nodesToUnload );
@@ -139,7 +169,7 @@ class LRUCache {
 
 	}
 
-	scheduleUnload( prioritySortCb, markAllUnused = true ) {
+	scheduleUnload( prioritySortCb = null, markAllUnused = true ) {
 
 		if ( ! this.scheduled ) {
 

+ 35 - 2
test/LRUCache.test.js

@@ -49,13 +49,46 @@ describe( 'LRUCache', () => {
 		cache.add( {}, () => {} );
 
 		expect( cache.isFull() ).toEqual( true );
-		cache.unloadUnusedContent( 0.25, null );
+		cache.unloadUnusedContent( null );
 		expect( cache.isFull() ).toEqual( true );
 		cache.markAllUnused();
-		cache.unloadUnusedContent( 0.25, null );
+		cache.unloadUnusedContent( null );
 
 		expect( cache.isFull() ).toEqual( false );
 
 	} );
 
+	it( 'should sort before unloading', () => {
+
+		const cache = new LRUCache();
+		cache.minSize = 0;
+		cache.maxSize = 10;
+		cache.unloadPercent = 1;
+
+		const arr = [];
+		const unloadCallback = item => {
+
+			arr.push( item.priority );
+
+		};
+
+		const P1 = { priority: 1 };
+		const P2 = { priority: 2 };
+		const P3 = { priority: 3 };
+		const P4 = { priority: 4 };
+
+		cache.add( P1, unloadCallback );
+		cache.add( P2, unloadCallback );
+		cache.add( P3, unloadCallback );
+		cache.add( P4, unloadCallback );
+
+		cache.markAllUnused();
+		cache.markUsed( P2 );
+		cache.markUsed( P3 );
+
+		cache.unloadUnusedContent( ( a, b ) => b.priority - a.priority );
+		expect( arr ).toEqual( [ 4, 1 ] );
+
+	} );
+
 } );