@@ -34,18 +34,21 @@ function computeIsLittleEndian() {
3434}
3535
3636const isLittleEndian = computeIsLittleEndian ( ) ;
37- let globalCounter = 0 ;
38-
39- function randomFileContents ( ) {
40- const numBytes = ( globalCounter % 128 ) + 2056 ;
41- globalCounter ++ ;
42- let result = new ArrayBuffer ( numBytes ) ;
43- let view = new Uint8Array ( result ) ;
44- for ( let i = 0 ; i < numBytes ; ++ i )
45- view [ i ] = ( i + globalCounter ) % 255 ;
46- return new DataView ( result ) ;
37+
38+ async function * randomFileContents ( ) {
39+ let counter = 1 ;
40+ while ( true ) {
41+ const numBytes = ( ( counter * 1192.18851371 ) % 2056 ) ;
42+ counter ++ ;
43+ let result = new ArrayBuffer ( numBytes ) ;
44+ let view = new Uint8Array ( result ) ;
45+ for ( let i = 0 ; i < numBytes ; ++ i )
46+ view [ i ] = ( i + counter ) % 255 ;
47+ yield new DataView ( result ) ;
48+ }
4749}
4850
51+
4952class File {
5053 constructor ( dataView , permissions ) {
5154 this . _data = dataView ;
@@ -55,6 +58,8 @@ class File {
5558
5659 set data ( dataView ) { this . _data = dataView ; }
5760
61+ get byteLength ( ) { return this . _data . byteLength ; }
62+
5863 swapByteOrder ( ) {
5964 let hash = 0x1a2b3c4d ;
6065 for ( let i = 0 ; i < Math . floor ( this . data . byteLength / 8 ) * 8 ; i += 8 ) {
@@ -144,62 +149,152 @@ class Directory {
144149 return count ;
145150 }
146151
152+ async totalFileSize ( ) {
153+ let size = 0 ;
154+ for await ( const { entry : file } of this . forEachFileRecursively ( ) ) {
155+ size += file . byteLength ;
156+ }
157+ return size ;
158+ }
159+
147160 async rm ( name ) {
148161 return this . structure . delete ( name ) ;
149162 }
163+
164+ async visit ( visitor ) {
165+ visitor . visitDir ( undefined , this ) ;
166+ for await ( const { name, entry, isDirectory} of this . ls ( ) ) {
167+ if ( isDirectory )
168+ await entry . visit ( visitor ) ;
169+ else
170+ visitor . visitFile ( name , entry ) ;
171+ }
172+ }
173+
150174}
151175
176+ const MAX_DIR_COUNT = 2500 ;
177+ const MAX_FILE_COUNT = 800 ;
178+
152179async function setupDirectory ( ) {
153180 const fs = new Directory ;
154181 let dirs = [ fs ] ;
155182 let counter = 0 ;
156183 for ( let dir of dirs ) {
157- for ( let i = 0 ; i < 10 ; ++ i ) {
158- if ( dirs . length < 400 && ( counter % 3 ) <= 1 ) {
184+ for ( let i = 0 ; i < 15 ; ++ i ) {
185+ if ( dirs . length <= MAX_DIR_COUNT ) {
159186 dirs . push ( await dir . addDirectory ( `dir-${ i } ` ) ) ;
160187 }
161188 counter ++ ;
162189 }
163190 }
164191
165- for ( let dir of dirs ) {
166- for ( let i = 0 ; i < 5 ; ++ i ) {
167- if ( ( counter % 3 ) === 0 ) {
168- await dir . addFile ( `file-${ i } ` , new File ( randomFileContents ( ) ) ) ;
169- }
170- counter ++ ;
171- }
192+ let fileCounter = 0 ;
193+ for await ( const fileContents of randomFileContents ( ) ) {
194+ const dirIndex = fileCounter * 107 ;
195+ const dir = dirs [ dirIndex % dirs . length ] ;
196+ await dir . addFile ( `file-${ fileCounter } ` , new File ( fileContents ) ) ;
197+ fileCounter ++
198+ if ( fileCounter >= MAX_FILE_COUNT )
199+ break ;
172200 }
173201
174202 return fs ;
175203}
176204
205+ class FSVisitor {
206+ visitFile ( name , file ) {
207+ }
208+
209+ visitDir ( name , dir ) {
210+ }
211+ }
212+
213+ class CountVisitor extends FSVisitor {
214+ fileCount = 0 ;
215+ dirCount = 0 ;
216+
217+ visitFile ( ) {
218+ this . fileCount ++ ;
219+ }
220+
221+ visitDir ( ) {
222+ this . dirCount ++ ;
223+ }
224+ }
225+
226+ class CountDracula extends FSVisitor {
227+ bytes = 0 ;
228+ visitFile ( name , file ) {
229+ this . bytes += file . byteLength ;
230+ }
231+ }
232+
233+
177234class Benchmark {
178- EXPECTED_FILE_COUNT = 666 ;
235+ EXPECTED_FILE_COUNT = 739 ;
179236
180237 totalFileCount = 0 ;
238+ totalDirCount = 0 ;
181239 lastFileHash = undefined ;
240+ fs ;
182241
183- async runIteration ( ) {
184- const fs = await setupDirectory ( ) ;
242+ async prepareForNextIteration ( ) {
243+ this . fs = await setupDirectory ( ) ;
244+ }
185245
186- for await ( let { entry : file } of fs . forEachFileRecursively ( ) ) {
246+ async runIteration ( ) {
247+ for await ( let { entry : file } of this . fs . forEachFileRecursively ( ) ) {
187248 this . lastFileHash = file . swapByteOrder ( ) ;
188249 }
189250
190- for await ( let { name, entry : dir } of fs . forEachDirectoryRecursively ( ) ) {
191- if ( ( await dir . fileCount ( ) ) > 3 ) {
192- for await ( let { name } of dir . forEachFile ( ) ) {
193- let result = await dir . rm ( name ) ;
194- if ( ! result )
195- throw new Error ( "rm should have returned true" ) ;
196- }
251+ let bytesDeleted = 0 ;
252+ let counter = 0 ;
253+ for await ( const { name, entry : dir } of this . fs . forEachDirectoryRecursively ( ) ) {
254+ const oldTotalSize = await dir . totalFileSize ( ) ;
255+ if ( await dir . fileCount ( ) === 0 )
256+ continue ;
257+ counter ++ ;
258+ if ( counter % 13 !== 0 )
259+ continue ;
260+ for await ( const { name } of dir . forEachFile ( ) ) {
261+ const result = await dir . rm ( name ) ;
262+ if ( ! result )
263+ throw new Error ( "rm should have returned true" ) ;
197264 }
265+ const totalReducedSize = oldTotalSize - dir . totalFileSize ( ) ;
266+ bytesDeleted += totalReducedSize ;
267+ }
268+ if ( bytesDeleted === 0 )
269+ throw new Error ( "Did not delete any files" ) ;
270+
271+ const countVisitor = new CountVisitor ( ) ;
272+ await this . fs . visit ( countVisitor ) ;
273+
274+ const countDracula = new CountDracula ( ) ;
275+ await this . fs . visit ( countDracula ) ;
276+
277+ let fileCount = 0 ;
278+ let fileBytes = 0 ;
279+ for await ( const { entry : file } of this . fs . forEachFileRecursively ( ) ) {
280+ fileCount ++
281+ fileBytes += file . byteLength ;
198282 }
283+ this . totalFileCount += fileCount ;
199284
200- for await ( let _ of fs . forEachFileRecursively ( ) ) {
201- this . totalFileCount ++ ;
285+ let dirCount = 1 ;
286+ for await ( let _ of this . fs . forEachDirectoryRecursively ( ) ) {
287+ dirCount ++ ;
202288 }
289+ this . totalDirCount += dirCount ;
290+
291+ if ( countVisitor . fileCount !== fileCount )
292+ throw new Error ( `Invalid total file count ${ countVisitor . fileCount } , expected ${ fileCount } .` ) ;
293+ if ( countDracula . bytes !== fileBytes )
294+ throw new Error ( `Invalid total file bytes ${ countDracula . bytes } , expected ${ fileBytes } .` ) ;
295+ if ( countVisitor . dirCount !== dirCount )
296+ throw new Error ( `Invalid total dir count ${ countVisitor . dirCount } , expected ${ dirCount } .` ) ;
297+
203298 }
204299
205300 validate ( iterations ) {
0 commit comments