@@ -52,12 +52,14 @@ import { AutoId } from '../util/misc';
52
52
import { SortedSet } from '../util/sorted_set' ;
53
53
54
54
import { Timestamp } from './timestamp' ;
55
+ import { QueryContext } from '../local/query_context' ;
55
56
56
57
export async function runPersistentCacheIndexPerformanceExperiment (
57
- log : ( ...args : unknown [ ] ) => unknown
58
+ log : ( ...args : unknown [ ] ) => unknown ,
59
+ logLevel : 'info' | 'debug'
58
60
) : Promise < void > {
59
61
const testObjects = await createTestObjects ( ) ;
60
- const experiment = new AutoIndexingExperiment ( log , testObjects ) ;
62
+ const experiment = new AutoIndexingExperiment ( log , logLevel , testObjects ) ;
61
63
await experiment . run ( ) ;
62
64
await testObjects . persistence . shutdown ( ) ;
63
65
}
@@ -73,7 +75,6 @@ interface TestObjects {
73
75
}
74
76
75
77
class AutoIndexingExperiment {
76
- private readonly logFunc : ( ...args : unknown [ ] ) => unknown ;
77
78
private readonly persistence : Persistence ;
78
79
private readonly indexManager : IndexManager ;
79
80
private readonly remoteDocumentCache : RemoteDocumentCache ;
@@ -83,7 +84,8 @@ class AutoIndexingExperiment {
83
84
private readonly documentOverlayCache : DocumentOverlayCache ;
84
85
85
86
constructor (
86
- logFunc : ( ...args : unknown [ ] ) => unknown ,
87
+ private readonly logFunc : ( ...args : unknown [ ] ) => unknown ,
88
+ private readonly logLevel : 'info' | 'debug' ,
87
89
testObjects : TestObjects
88
90
) {
89
91
this . logFunc = logFunc ;
@@ -100,10 +102,10 @@ class AutoIndexingExperiment {
100
102
// Every set contains 10 documents
101
103
const numOfSet = 100 ;
102
104
// could overflow. Currently it is safe when numOfSet set to 1000 and running on macbook M1
103
- const totalBeforeIndex = 0 ;
104
- const totalAfterIndex = 0 ;
105
- const totalDocumentCount = 0 ;
106
- const totalResultCount = 0 ;
105
+ let totalBeforeIndex = 0 ;
106
+ let totalAfterIndex = 0 ;
107
+ let totalDocumentCount = 0 ;
108
+ let totalResultCount = 0 ;
107
109
108
110
// Temperate heuristic, gets when setting numOfSet to 1000.
109
111
const withoutIndex = 1 ;
@@ -117,7 +119,9 @@ class AutoIndexingExperiment {
117
119
// portion stands for the percentage of documents matching query
118
120
for ( let portion = 0 ; portion <= 10 ; portion ++ ) {
119
121
for ( let numOfFields = 1 ; numOfFields <= 31 ; numOfFields += 10 ) {
120
- const basePath = 'documentCount' + totalSetCount ;
122
+ const basePath =
123
+ `${ AutoId . newId ( ) } _totalSetCount${ totalSetCount } _` +
124
+ `portion${ portion } _numOfFields${ numOfFields } ` ;
121
125
const query = createQuery ( basePath , 'match' , Operator . EQUAL , true ) ;
122
126
123
127
// Creates a full matched index for given query.
@@ -135,6 +139,83 @@ class AutoIndexingExperiment {
135
139
numOfFields
136
140
) ;
137
141
await this . createMutationForCollection ( basePath , totalSetCount ) ;
142
+
143
+ // runs query using full collection scan.
144
+ let millisecondsBeforeAuto : number ;
145
+ let contextWithoutIndexDocumentReadCount : number ;
146
+ {
147
+ const contextWithoutIndex = new QueryContext ( ) ;
148
+ const beforeAutoStart = performance . now ( ) ;
149
+ const beforeAutoResults = await this . persistence . runTransaction (
150
+ 'executeFullCollectionScan' ,
151
+ 'readwrite' ,
152
+ txn =>
153
+ this . queryEngine . executeFullCollectionScan (
154
+ txn ,
155
+ query ,
156
+ contextWithoutIndex
157
+ )
158
+ ) ;
159
+ const beforeAutoEnd = performance . now ( ) ;
160
+ millisecondsBeforeAuto = beforeAutoEnd - beforeAutoStart ;
161
+ totalBeforeIndex += millisecondsBeforeAuto ;
162
+ totalDocumentCount += contextWithoutIndex . documentReadCount ;
163
+ contextWithoutIndexDocumentReadCount =
164
+ contextWithoutIndex . documentReadCount ;
165
+ if ( portion * totalSetCount != beforeAutoResults . size ) {
166
+ throw new Error (
167
+ `${
168
+ portion * totalSetCount
169
+ } !={beforeAutoResults.size} (portion * totalSetCount != beforeAutoResults.size)`
170
+ ) ;
171
+ }
172
+ this . logDebug (
173
+ `Running query without using the index took ${ millisecondsBeforeAuto } ms`
174
+ ) ;
175
+ }
176
+
177
+ // runs query using index look up.
178
+ let millisecondsAfterAuto : number ;
179
+ let autoResultsSize : number ;
180
+ {
181
+ const autoStart = performance . now ( ) ;
182
+ const autoResults = await this . persistence . runTransaction (
183
+ 'performQueryUsingIndex' ,
184
+ 'readwrite' ,
185
+ txn => this . queryEngine . performQueryUsingIndex ( txn , query )
186
+ ) ;
187
+ if ( autoResults === null ) {
188
+ throw new Error ( 'performQueryUsingIndex() returned null' ) ;
189
+ }
190
+ const autoEnd = performance . now ( ) ;
191
+ millisecondsAfterAuto = autoEnd - autoStart ;
192
+ totalAfterIndex += millisecondsAfterAuto ;
193
+ if ( portion * totalSetCount != autoResults . size ) {
194
+ throw new Error (
195
+ `${
196
+ portion * totalSetCount
197
+ } !={beforeAutoResults.size} (portion * totalSetCount != beforeAutoResults.size)`
198
+ ) ;
199
+ }
200
+ this . logDebug (
201
+ `Running query using the index took ${ millisecondsAfterAuto } ms`
202
+ ) ;
203
+ totalResultCount += autoResults . size ;
204
+ autoResultsSize = autoResults . size ;
205
+ }
206
+
207
+ if ( millisecondsBeforeAuto > millisecondsAfterAuto ) {
208
+ this . log (
209
+ `Auto Indexing saves time when total of documents inside ` +
210
+ `collection is ${ totalSetCount * 10 } . ` +
211
+ `The matching percentage is ${ portion } 0%. ` +
212
+ `And each document contains ${ numOfFields } fields. ` +
213
+ `Weight result for without auto indexing is ` +
214
+ `${ withoutIndex * contextWithoutIndexDocumentReadCount } . ` +
215
+ `And weight result for auto indexing is ` +
216
+ `${ withIndex * autoResultsSize } `
217
+ ) ;
218
+ }
138
219
}
139
220
}
140
221
}
@@ -146,7 +227,7 @@ class AutoIndexingExperiment {
146
227
portion : number /*0 - 10*/ ,
147
228
numOfFields : number /* 1 - 30*/
148
229
) : Promise < void > {
149
- this . log (
230
+ this . logDebug (
150
231
`Creating test collection: "${ basePath } " ` +
151
232
`totalSetCount=${ totalSetCount } ` +
152
233
`portion=${ portion } ` +
@@ -279,6 +360,12 @@ class AutoIndexingExperiment {
279
360
) ;
280
361
}
281
362
363
+ logDebug ( ...args : unknown [ ] ) : void {
364
+ if ( this . logLevel === 'debug' ) {
365
+ this . logFunc ( ...args ) ;
366
+ }
367
+ }
368
+
282
369
log ( ...args : unknown [ ] ) : void {
283
370
this . logFunc ( ...args ) ;
284
371
}
0 commit comments