11import { utf8DecodeJs } from "./utils/utf8" ;
22
3- interface KeyCacheRecord {
4- readonly bytes : Uint8Array ;
5- readonly value : string ;
6- }
7-
83const DEFAULT_MAX_KEY_LENGTH = 16 ;
94const DEFAULT_MAX_LENGTH_PER_KEY = 16 ;
105
116export interface KeyDecoder {
127 canBeCached ( byteLength : number ) : boolean ;
138 decode ( bytes : Uint8Array , inputOffset : number , byteLength : number ) : string ;
149}
10+ interface KeyCacheRecord {
11+ readonly bytes : Uint8Array ;
12+ readonly str : string ;
13+ }
1514
1615export class CachedKeyDecoder implements KeyDecoder {
1716 hit = 0 ;
1817 miss = 0 ;
1918 private readonly caches : Array < Array < KeyCacheRecord > > ;
2019
2120 constructor ( readonly maxKeyLength = DEFAULT_MAX_KEY_LENGTH , readonly maxLengthPerKey = DEFAULT_MAX_LENGTH_PER_KEY ) {
22- // avoid `new Array(N)` to create a non-sparse array for performance.
21+ // avoid `new Array(N)`, which makes a sparse array,
22+ // because a sparse array is typically slower than a non-sparse array.
2323 this . caches = [ ] ;
2424 for ( let i = 0 ; i < this . maxKeyLength ; i ++ ) {
2525 this . caches . push ( [ ] ) ;
@@ -30,7 +30,7 @@ export class CachedKeyDecoder implements KeyDecoder {
3030 return byteLength > 0 && byteLength <= this . maxKeyLength ;
3131 }
3232
33- private get ( bytes : Uint8Array , inputOffset : number , byteLength : number ) : string | null {
33+ private find ( bytes : Uint8Array , inputOffset : number , byteLength : number ) : string | null {
3434 const records = this . caches [ byteLength - 1 ] ! ;
3535
3636 FIND_CHUNK: for ( const record of records ) {
@@ -41,36 +41,36 @@ export class CachedKeyDecoder implements KeyDecoder {
4141 continue FIND_CHUNK;
4242 }
4343 }
44- return record . value ;
44+ return record . str ;
4545 }
4646 return null ;
4747 }
4848
4949 private store ( bytes : Uint8Array , value : string ) {
5050 const records = this . caches [ bytes . length - 1 ] ! ;
51- const record : KeyCacheRecord = { bytes, value } ;
51+ const record : KeyCacheRecord = { bytes, str : value } ;
5252
5353 if ( records . length >= this . maxLengthPerKey ) {
5454 // `records` are full!
55- // Set `record` to a randomized position.
55+ // Set `record` to an arbitrary position.
5656 records [ ( Math . random ( ) * records . length ) | 0 ] = record ;
5757 } else {
5858 records . push ( record ) ;
5959 }
6060 }
6161
6262 public decode ( bytes : Uint8Array , inputOffset : number , byteLength : number ) : string {
63- const cachedValue = this . get ( bytes , inputOffset , byteLength ) ;
63+ const cachedValue = this . find ( bytes , inputOffset , byteLength ) ;
6464 if ( cachedValue != null ) {
6565 this . hit ++ ;
6666 return cachedValue ;
6767 }
6868 this . miss ++ ;
6969
70- const value = utf8DecodeJs ( bytes , inputOffset , byteLength ) ;
70+ const str = utf8DecodeJs ( bytes , inputOffset , byteLength ) ;
7171 // Ensure to copy a slice of bytes because the byte may be NodeJS Buffer and Buffer#slice() returns a reference to its internal ArrayBuffer.
7272 const slicedCopyOfBytes = Uint8Array . prototype . slice . call ( bytes , inputOffset , inputOffset + byteLength ) ;
73- this . store ( slicedCopyOfBytes , value ) ;
74- return value ;
73+ this . store ( slicedCopyOfBytes , str ) ;
74+ return str ;
7575 }
7676}
0 commit comments