@mark1russell7/rigor-bench 0.2.14 → 0.2.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +60 -1
- package/build/index.d.ts +427 -234
- package/build/index.d.ts.map +1 -1
- package/build/index.js +414 -13
- package/build/index.js.map +1 -1
- package/package.json +2 -2
package/build/index.d.ts
CHANGED
|
@@ -124,239 +124,6 @@ export declare function budgetLookSpend(looks: readonly BudgetLook[]): number;
|
|
|
124
124
|
* - The field `fails` is true only for the outcome `beyond`. Tell a final `cannot decide` to the reader of the run.
|
|
125
125
|
*/
|
|
126
126
|
export declare function budgetLooksVerdict(rounds: readonly BudgetRound[], aa: readonly BudgetRound[], options: BudgetLooksOptions): BudgetLooksVerdict;
|
|
127
|
-
/** One time of the control in one group. */
|
|
128
|
-
interface ControlRow {
|
|
129
|
-
/** The name of the group: a run, or a shard of one run. */
|
|
130
|
-
readonly group: string;
|
|
131
|
-
/** The name of a class of work. The same key in two groups names equal work, so a ratio of the two measures the load. */
|
|
132
|
-
readonly key: string;
|
|
133
|
-
/** The time. It is finite and more than 0. */
|
|
134
|
-
readonly value: number;
|
|
135
|
-
/** This field is true when the run stopped the case at `value`. Thus the real time is at least `value`. */
|
|
136
|
-
readonly censored?: boolean;
|
|
137
|
-
}
|
|
138
|
-
/** The options of `controlFactor`. */
|
|
139
|
-
interface ControlOptions {
|
|
140
|
-
/** The group that the factors compare with. Without it, the base of each key is the median of that key over the groups. */
|
|
141
|
-
readonly base?: string;
|
|
142
|
-
/** The least number of keys in a factor. A group with fewer keys has no factor. The default is 5. */
|
|
143
|
-
readonly minPairs?: number;
|
|
144
|
-
}
|
|
145
|
-
/** The counts of one group, with or without a factor. */
|
|
146
|
-
interface GroupCounts {
|
|
147
|
-
readonly group: string;
|
|
148
|
-
/** The number of keys that the factor reads. */
|
|
149
|
-
readonly pairs: number;
|
|
150
|
-
/** The number of keys that this function left out because a time of the key was censored. The factor reads low when this count is not 0. */
|
|
151
|
-
readonly censored: number;
|
|
152
|
-
/** The number of keys of this group that have no time to compare with, so no ratio reads them. */
|
|
153
|
-
readonly unshared: number;
|
|
154
|
-
}
|
|
155
|
-
/** The factor of one group. */
|
|
156
|
-
interface MeasuredFactor extends GroupCounts {
|
|
157
|
-
/** The median ratio of the times of this group over the base. A factor of 1.6 means that this group took 1.6 times as long. */
|
|
158
|
-
readonly factor: number;
|
|
159
|
-
/** The quartiles of the ratios. A wide spread means that one factor does not explain the load. */
|
|
160
|
-
readonly low: number;
|
|
161
|
-
readonly high: number;
|
|
162
|
-
}
|
|
163
|
-
/** A group with too few usable keys. It has no factor, and the other groups keep theirs. */
|
|
164
|
-
interface NoFactor extends GroupCounts {
|
|
165
|
-
readonly factor: undefined;
|
|
166
|
-
/** The reason that this group has no factor. */
|
|
167
|
-
readonly reason: string;
|
|
168
|
-
}
|
|
169
|
-
/** The result of one group. Read `factor` first: a group with too few usable keys has no factor. */
|
|
170
|
-
type GroupFactor = MeasuredFactor | NoFactor;
|
|
171
|
-
/** The factors of a run, with the base that they use. */
|
|
172
|
-
interface ControlFactors {
|
|
173
|
-
/** The base group, or undefined when the base of each key is its median over the groups. */
|
|
174
|
-
readonly base: string | undefined;
|
|
175
|
-
readonly factors: readonly GroupFactor[];
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* This function gives the load factor of each group from the times of a control.
|
|
179
|
-
*
|
|
180
|
-
* With `base`, a factor compares the keys that a group shares with that group. Without it, a factor compares each time with the median of its key over the groups.
|
|
181
|
-
* A key names a class of work, so equal keys in two groups mean equal work. Each group has at most one row for a key.
|
|
182
|
-
*
|
|
183
|
-
* A censored time is only a lower limit, so no ratio reads it, and the result counts those keys. A run stops its slowest cases, so a factor reads low when `censored` is not 0.
|
|
184
|
-
*
|
|
185
|
-
* A group with too few usable keys gets an entry with no factor and its reason, so the other groups keep their factors. This function refuses a result where no group has a factor.
|
|
186
|
-
*/
|
|
187
|
-
export declare function controlFactor(rows: readonly ControlRow[], options?: ControlOptions): ControlFactors;
|
|
188
|
-
/** The format name of a ladder. It changes when a reader of an older form cannot read the data. */
|
|
189
|
-
export declare const LADDER_FORMAT = "rigor-ladder/1";
|
|
190
|
-
/** One dimension of a ladder, for example tenants or nodes. */
|
|
191
|
-
interface LadderDimension {
|
|
192
|
-
readonly name: string;
|
|
193
|
-
/** What one unit of the dimension is, in plain words. */
|
|
194
|
-
readonly describe: string;
|
|
195
|
-
}
|
|
196
|
-
/** A budget on the median of each case, for example the time of a read. A record gives rounds and an A/A arm. */
|
|
197
|
-
interface MedianBudget {
|
|
198
|
-
readonly kind: "median";
|
|
199
|
-
readonly measure: string;
|
|
200
|
-
/** The unit of the limit and of the values. */
|
|
201
|
-
readonly unit: string;
|
|
202
|
-
/** The largest median that the budget permits. */
|
|
203
|
-
readonly limit: number;
|
|
204
|
-
/** The largest difference between the medians of the two arms. A larger difference makes the run too noisy. */
|
|
205
|
-
readonly maxDifference: number;
|
|
206
|
-
/** The level of the interval of each median. The default is 0.95. */
|
|
207
|
-
readonly caseLevel?: number;
|
|
208
|
-
}
|
|
209
|
-
/** A budget on the share of failed trials, for example failed requests. A record gives failures and trials. */
|
|
210
|
-
interface RateBudget {
|
|
211
|
-
readonly kind: "rate";
|
|
212
|
-
readonly measure: string;
|
|
213
|
-
/** The largest share of failures that the budget permits, from 0 to 1. */
|
|
214
|
-
readonly limit: number;
|
|
215
|
-
}
|
|
216
|
-
/** A budget on the largest value of a set of drills, for example the writes that a restore lost. One bad drill is `beyond`. */
|
|
217
|
-
interface WorstBudget {
|
|
218
|
-
readonly kind: "worst";
|
|
219
|
-
readonly measure: string;
|
|
220
|
-
readonly unit: string;
|
|
221
|
-
/** The largest value that the budget permits in any drill. */
|
|
222
|
-
readonly limit: number;
|
|
223
|
-
/** The number of drills that a verdict needs, 1 or more. With fewer, the budget is `cannot decide`. */
|
|
224
|
-
readonly minDrills: number;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* A budget on a high quantile, for example the p99 of a read. A record gives the values. The verdict is the distribution-free
|
|
228
|
-
* interval of the quantile against the limit. A p99 needs 368 independent values at the level 0.95: refer to `quantileSamples`.
|
|
229
|
-
* Successive times of one run can follow each other. Space them apart, or give one value for each run.
|
|
230
|
-
*
|
|
231
|
-
* The evidence can also hold `censored`: a lower bound for each arrival with no reply, and for each arrival that was not
|
|
232
|
-
* sent. The bound is the time that the arrival waited. The true value is that bound or more, with no upper limit. Thus the
|
|
233
|
-
* low end of the interval reads the bounds, and the high end reads each censored value as `Infinity`. A `beyond` stays
|
|
234
|
-
* provable from the bounds alone. A `within` needs real replies up to the upper rank of the interval.
|
|
235
|
-
*/
|
|
236
|
-
interface QuantileBudget {
|
|
237
|
-
readonly kind: "quantile";
|
|
238
|
-
readonly measure: string;
|
|
239
|
-
/** The unit of the limit and of the values. */
|
|
240
|
-
readonly unit: string;
|
|
241
|
-
/** The quantile, more than 0 and less than 1, for example 0.99. */
|
|
242
|
-
readonly quantile: number;
|
|
243
|
-
/** The largest quantile that the budget permits. */
|
|
244
|
-
readonly limit: number;
|
|
245
|
-
/** The level of the interval. The default is 0.95. */
|
|
246
|
-
readonly level?: number;
|
|
247
|
-
}
|
|
248
|
-
/** One budget of a rung. */
|
|
249
|
-
type RungBudget = MedianBudget | QuantileBudget | RateBudget | WorstBudget;
|
|
250
|
-
/** One rung of a ladder. */
|
|
251
|
-
interface Rung {
|
|
252
|
-
/** The name of the rung, unique in the ladder. */
|
|
253
|
-
readonly name: string;
|
|
254
|
-
/** The size of the rung in each dimension that it names. */
|
|
255
|
-
readonly at: Readonly<Record<string, number>>;
|
|
256
|
-
readonly budgets: readonly RungBudget[];
|
|
257
|
-
/** The name of the automatic test that holds the rung. */
|
|
258
|
-
readonly test: string;
|
|
259
|
-
/** True when a gate holds the rung: the verdict fails when the rung is not `within`. */
|
|
260
|
-
readonly locked?: boolean;
|
|
261
|
-
}
|
|
262
|
-
/** The ladder of one subject. The rungs go from the smallest to the largest. */
|
|
263
|
-
interface Ladder {
|
|
264
|
-
readonly format: typeof LADDER_FORMAT;
|
|
265
|
-
/** The product or the service that the ladder is for. */
|
|
266
|
-
readonly subject: string;
|
|
267
|
-
readonly dimensions: readonly LadderDimension[];
|
|
268
|
-
readonly rungs: readonly Rung[];
|
|
269
|
-
}
|
|
270
|
-
/** The measured evidence for one budget. Its `kind` is the kind of the budget. */
|
|
271
|
-
type RungEvidence = {
|
|
272
|
-
readonly kind: "median";
|
|
273
|
-
readonly measure: string;
|
|
274
|
-
readonly rounds: readonly BudgetRound[];
|
|
275
|
-
readonly aa: readonly BudgetRound[];
|
|
276
|
-
} | {
|
|
277
|
-
readonly kind: "quantile";
|
|
278
|
-
readonly measure: string;
|
|
279
|
-
readonly values: readonly number[];
|
|
280
|
-
readonly censored?: readonly number[];
|
|
281
|
-
} | {
|
|
282
|
-
readonly kind: "rate";
|
|
283
|
-
readonly measure: string;
|
|
284
|
-
readonly failures: number;
|
|
285
|
-
readonly trials: number;
|
|
286
|
-
} | {
|
|
287
|
-
readonly kind: "worst";
|
|
288
|
-
readonly measure: string;
|
|
289
|
-
readonly values: readonly number[];
|
|
290
|
-
};
|
|
291
|
-
/** One run of the test of a rung. */
|
|
292
|
-
interface RungRecord {
|
|
293
|
-
/** The name of the rung. */
|
|
294
|
-
readonly rung: string;
|
|
295
|
-
/** The commit that the run measured. */
|
|
296
|
-
readonly commit: string;
|
|
297
|
-
/** The time of the run, as an ISO 8601 string. */
|
|
298
|
-
readonly at: string;
|
|
299
|
-
/** What the run did for real, for example "2 processes" or "a restore from a real backup". */
|
|
300
|
-
readonly real: readonly string[];
|
|
301
|
-
/** What the run made up, for example "90 % of the tenants as data at rest". An empty list states that nothing was synthetic. */
|
|
302
|
-
readonly synthetic: readonly string[];
|
|
303
|
-
readonly evidence: readonly RungEvidence[];
|
|
304
|
-
}
|
|
305
|
-
/** The verdict of one budget of a rung. */
|
|
306
|
-
interface BudgetResult {
|
|
307
|
-
readonly measure: string;
|
|
308
|
-
readonly outcome: BudgetOutcome;
|
|
309
|
-
/** The reason of the outcome, in one sentence, with the numbers. */
|
|
310
|
-
readonly reason: string;
|
|
311
|
-
}
|
|
312
|
-
/** The verdict of one rung. */
|
|
313
|
-
interface RungVerdict {
|
|
314
|
-
readonly rung: string;
|
|
315
|
-
readonly test: string;
|
|
316
|
-
readonly locked: boolean;
|
|
317
|
-
readonly outcome: BudgetOutcome;
|
|
318
|
-
/** The reason of the outcome, in one sentence. */
|
|
319
|
-
readonly reason: string;
|
|
320
|
-
readonly budgets: readonly BudgetResult[];
|
|
321
|
-
/** The commit of the record, or undefined when the rung has no record. */
|
|
322
|
-
readonly commit: string | undefined;
|
|
323
|
-
readonly real: readonly string[];
|
|
324
|
-
readonly synthetic: readonly string[];
|
|
325
|
-
}
|
|
326
|
-
/** The verdict of a ladder. */
|
|
327
|
-
interface LadderVerdict {
|
|
328
|
-
readonly subject: string;
|
|
329
|
-
/** The highest rung with each rung up to it `within`, or undefined when the first rung is not `within`. */
|
|
330
|
-
readonly held: string | undefined;
|
|
331
|
-
/** The first rung that is not `within`, or undefined when each rung is `within`. */
|
|
332
|
-
readonly next: string | undefined;
|
|
333
|
-
/** True when a locked rung is not `within`. A rung with no result is not held, so `cannot decide` fails too. */
|
|
334
|
-
readonly failed: boolean;
|
|
335
|
-
/** The reason of `failed`, in one sentence. */
|
|
336
|
-
readonly reason: string;
|
|
337
|
-
readonly rungs: readonly RungVerdict[];
|
|
338
|
-
}
|
|
339
|
-
/** The options of a ladder verdict. */
|
|
340
|
-
interface LadderOptions {
|
|
341
|
-
/** The time of the verdict, as an ISO 8601 string. It is an input, so that a verdict is the same at each read. */
|
|
342
|
-
readonly now: string;
|
|
343
|
-
/** The largest age of a record, in days. An older record gives `cannot decide`. The default accepts any age. */
|
|
344
|
-
readonly maxAgeDays?: number;
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* This function gives each problem of a ladder as data, or an empty list. A ladder needs a subject, one dimension or more,
|
|
348
|
-
* and one rung or more. Names are unique. Each rung names a test and has budgets. From one rung to the next, each dimension
|
|
349
|
-
* that the two rungs name grows.
|
|
350
|
-
*/
|
|
351
|
-
export declare function checkLadder(ladder: Ladder): readonly string[];
|
|
352
|
-
/** This function gives the verdict of one rung from its record. With no record, the rung is `cannot decide`. */
|
|
353
|
-
export declare function rungVerdict(rung: Rung, record: RungRecord | undefined, options: LadderOptions): RungVerdict;
|
|
354
|
-
/**
|
|
355
|
-
* This function gives the verdict of a ladder from the records of its rungs. It uses the newest record of each rung, so an
|
|
356
|
-
* older pass does not hide a newer failure. A rung high up does not count when a rung below it is not `within`. It throws
|
|
357
|
-
* a `RangeError` for a ladder with problems, because a verdict on a bad ladder has no meaning. See `checkLadder`.
|
|
358
|
-
*/
|
|
359
|
-
export declare function ladderVerdict(ladder: Ladder, records: readonly RungRecord[], options: LadderOptions): LadderVerdict;
|
|
360
127
|
/**
|
|
361
128
|
* The two kinds of an A/A band.
|
|
362
129
|
* - The band `case` holds the ratio of one A/A case. It is wide, so it finds only a large change.
|
|
@@ -698,6 +465,432 @@ interface RunPairs {
|
|
|
698
465
|
* It balances the records of each pair with `balanceOrders` first. It refuses an `aaPair` that the run does not have.
|
|
699
466
|
*/
|
|
700
467
|
export declare function armVerdicts(run: RunPairs, aaPair: string, options?: VerdictOptions): Record<string, TimeVerdict>;
|
|
468
|
+
/** The three results of a gate. */
|
|
469
|
+
type GateOutcome = "pass" | "block" | "no read";
|
|
470
|
+
/** The fields of a case that a gate reads. The cases of `limitVerdict`, `budgetVerdict` and the verdict of this file have them. */
|
|
471
|
+
interface GateCaseOutcome {
|
|
472
|
+
readonly case: string;
|
|
473
|
+
readonly outcome: LimitOutcome;
|
|
474
|
+
}
|
|
475
|
+
/** The result of a gate, with the cases that make it. */
|
|
476
|
+
interface Gate {
|
|
477
|
+
readonly outcome: GateOutcome;
|
|
478
|
+
/** The reason of the result, in one sentence. */
|
|
479
|
+
readonly reason: string;
|
|
480
|
+
/** The cases with the outcome `beyond`. */
|
|
481
|
+
readonly blocks: readonly string[];
|
|
482
|
+
/** The cases with the outcome `cannot decide`. */
|
|
483
|
+
readonly noRead: readonly string[];
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* This function gives the gate of a list of case outcomes.
|
|
487
|
+
* - The result is "block" when a case is `beyond`.
|
|
488
|
+
* - The result is "pass" when each case is `within`.
|
|
489
|
+
* - Each other result is "no read", and so is a list with no cases. A caller does not count "no read" as a pass.
|
|
490
|
+
*/
|
|
491
|
+
export declare function gateOf(cases: readonly GateCaseOutcome[]): Gate;
|
|
492
|
+
/** The word of a case for the claim "not slower by more than the margin". The word "not slower" is apart from `same` of `timeVerdict`. */
|
|
493
|
+
type NotSlowerRead = "not slower" | "slower" | "no read";
|
|
494
|
+
/** The looks of `notSlowerVerdict`: the rounds in each job. The level of the family has an equal share at each look. */
|
|
495
|
+
export declare const GATE_LOOKS: readonly number[];
|
|
496
|
+
/** The options of `notSlowerVerdict`. */
|
|
497
|
+
interface NotSlowerOptions {
|
|
498
|
+
/** The margin of each case on a log scale: a number, or a function of the name of the case. */
|
|
499
|
+
readonly margin: number | ((name: string) => number);
|
|
500
|
+
/** The chance of a false "not slower", and apart from it the chance of a false "slower", over the family and all looks. The default is 0.05. */
|
|
501
|
+
readonly level?: number;
|
|
502
|
+
/** The looks: even whole numbers in rising order. The default is `GATE_LOOKS`. */
|
|
503
|
+
readonly looks?: readonly number[];
|
|
504
|
+
/** The count of jobs that each need the bound. The default is 2, because more rounds do not remove a difference between jobs. */
|
|
505
|
+
readonly jobs?: number;
|
|
506
|
+
}
|
|
507
|
+
/** The read of one case in one job, at one look. */
|
|
508
|
+
interface GateJobRead {
|
|
509
|
+
readonly job: string;
|
|
510
|
+
/** The pairs of rounds that the look uses. Below the rounds of the look, the job has not reached the look. */
|
|
511
|
+
readonly rounds: number;
|
|
512
|
+
/** The count of pairs with a difference below the margin. */
|
|
513
|
+
readonly below: number;
|
|
514
|
+
/** The count of pairs with a difference above the margin. */
|
|
515
|
+
readonly above: number;
|
|
516
|
+
/** The one-sided p of the sign test of the claim "the median difference is below the margin". */
|
|
517
|
+
readonly notSlower: number;
|
|
518
|
+
/** The one-sided p of the sign test of the claim "the median difference is above the margin". */
|
|
519
|
+
readonly slower: number;
|
|
520
|
+
/** The median of the differences, or undefined when the job has not reached the look. */
|
|
521
|
+
readonly centre: number | undefined;
|
|
522
|
+
}
|
|
523
|
+
/** The verdict of one case. */
|
|
524
|
+
interface CaseGate extends GateCaseOutcome {
|
|
525
|
+
readonly read: NotSlowerRead;
|
|
526
|
+
readonly margin: number;
|
|
527
|
+
/** The rounds of the look that decides the case, or undefined when the case has no outcome. */
|
|
528
|
+
readonly look: number | undefined;
|
|
529
|
+
/** The reads of each job, at the look that decides the case, or else at the last look that a job reached. */
|
|
530
|
+
readonly jobs: readonly GateJobRead[];
|
|
531
|
+
/** The reason of the outcome, in one sentence. */
|
|
532
|
+
readonly reason: string;
|
|
533
|
+
}
|
|
534
|
+
/** The gate of the claim "not slower by more than the margin", with the facts that it uses. */
|
|
535
|
+
interface NotSlowerVerdict extends Gate {
|
|
536
|
+
readonly level: number;
|
|
537
|
+
readonly looks: readonly number[];
|
|
538
|
+
/** The count of jobs that each need the bound. */
|
|
539
|
+
readonly need: number;
|
|
540
|
+
readonly cases: readonly CaseGate[];
|
|
541
|
+
/** The cases with no outcome that can have another look. The list is empty when the verdict is final. */
|
|
542
|
+
readonly more: readonly BudgetMore[];
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* This function gives the gate of the claim "the candidate is not slower than the A/A arm by more than the margin" for each
|
|
546
|
+
* case. A one-sided bound answers the claim. Thus a case with its whole interval under the margin reads "not slower", also
|
|
547
|
+
* when its interval holds 1.
|
|
548
|
+
*
|
|
549
|
+
* - In each job, the sign test compares the median of the differences with the margin. It uses no random numbers.
|
|
550
|
+
* - A case reads in `jobs` jobs or more: `partialConjunction` joins the p of each job, with no condition on how they depend.
|
|
551
|
+
* - The level is for the family. Each look has `level / looks` of it, and `holm` corrects each look over all cases.
|
|
552
|
+
* - The first look with an outcome decides a case. Later rounds do not change it. Each look uses the first rounds of a job.
|
|
553
|
+
* - The result is "block" when a case reads "slower", and "pass" when each case reads "not slower".
|
|
554
|
+
* - Each other result is "no read". The field `more` gives the next look of each case. After the last look, the caller adds jobs.
|
|
555
|
+
*
|
|
556
|
+
* The level needs independent rounds. Rounds with a shared cause, for example a slow computer for one job, do not have it.
|
|
557
|
+
* A job that a caller adds after the last look is one more look, and the level does not count it.
|
|
558
|
+
*/
|
|
559
|
+
export declare function notSlowerVerdict(jobs: readonly JobRecords[], options: NotSlowerOptions): NotSlowerVerdict;
|
|
560
|
+
/** One time of the control in one group. */
|
|
561
|
+
interface ControlRow {
|
|
562
|
+
/** The name of the group: a run, or a shard of one run. */
|
|
563
|
+
readonly group: string;
|
|
564
|
+
/** The name of a class of work. The same key in two groups names equal work, so a ratio of the two measures the load. */
|
|
565
|
+
readonly key: string;
|
|
566
|
+
/** The time. It is finite and more than 0. */
|
|
567
|
+
readonly value: number;
|
|
568
|
+
/** This field is true when the run stopped the case at `value`. Thus the real time is at least `value`. */
|
|
569
|
+
readonly censored?: boolean;
|
|
570
|
+
}
|
|
571
|
+
/** The options of `controlFactor`. */
|
|
572
|
+
interface ControlOptions {
|
|
573
|
+
/** The group that the factors compare with. Without it, the base of each key is the median of that key over the groups. */
|
|
574
|
+
readonly base?: string;
|
|
575
|
+
/** The least number of keys in a factor. A group with fewer keys has no factor. The default is 5. */
|
|
576
|
+
readonly minPairs?: number;
|
|
577
|
+
}
|
|
578
|
+
/** The counts of one group, with or without a factor. */
|
|
579
|
+
interface GroupCounts {
|
|
580
|
+
readonly group: string;
|
|
581
|
+
/** The number of keys that the factor reads. */
|
|
582
|
+
readonly pairs: number;
|
|
583
|
+
/** The number of keys that this function left out because a time of the key was censored. The factor reads low when this count is not 0. */
|
|
584
|
+
readonly censored: number;
|
|
585
|
+
/** The number of keys of this group that have no time to compare with, so no ratio reads them. */
|
|
586
|
+
readonly unshared: number;
|
|
587
|
+
}
|
|
588
|
+
/** The factor of one group. */
|
|
589
|
+
interface MeasuredFactor extends GroupCounts {
|
|
590
|
+
/** The median ratio of the times of this group over the base. A factor of 1.6 means that this group took 1.6 times as long. */
|
|
591
|
+
readonly factor: number;
|
|
592
|
+
/** The quartiles of the ratios. A wide spread means that one factor does not explain the load. */
|
|
593
|
+
readonly low: number;
|
|
594
|
+
readonly high: number;
|
|
595
|
+
}
|
|
596
|
+
/** A group with too few usable keys. It has no factor, and the other groups keep theirs. */
|
|
597
|
+
interface NoFactor extends GroupCounts {
|
|
598
|
+
readonly factor: undefined;
|
|
599
|
+
/** The reason that this group has no factor. */
|
|
600
|
+
readonly reason: string;
|
|
601
|
+
}
|
|
602
|
+
/** The result of one group. Read `factor` first: a group with too few usable keys has no factor. */
|
|
603
|
+
type GroupFactor = MeasuredFactor | NoFactor;
|
|
604
|
+
/** The factors of a run, with the base that they use. */
|
|
605
|
+
interface ControlFactors {
|
|
606
|
+
/** The base group, or undefined when the base of each key is its median over the groups. */
|
|
607
|
+
readonly base: string | undefined;
|
|
608
|
+
readonly factors: readonly GroupFactor[];
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* This function gives the load factor of each group from the times of a control.
|
|
612
|
+
*
|
|
613
|
+
* With `base`, a factor compares the keys that a group shares with that group. Without it, a factor compares each time with the median of its key over the groups.
|
|
614
|
+
* A key names a class of work, so equal keys in two groups mean equal work. Each group has at most one row for a key.
|
|
615
|
+
*
|
|
616
|
+
* A censored time is only a lower limit, so no ratio reads it, and the result counts those keys. A run stops its slowest cases, so a factor reads low when `censored` is not 0.
|
|
617
|
+
*
|
|
618
|
+
* A group with too few usable keys gets an entry with no factor and its reason, so the other groups keep their factors. This function refuses a result where no group has a factor.
|
|
619
|
+
*/
|
|
620
|
+
export declare function controlFactor(rows: readonly ControlRow[], options?: ControlOptions): ControlFactors;
|
|
621
|
+
/** The format name of a ladder. It changes when a reader of an older form cannot read the data. */
|
|
622
|
+
export declare const LADDER_FORMAT = "rigor-ladder/1";
|
|
623
|
+
/** One dimension of a ladder, for example tenants or nodes. */
|
|
624
|
+
interface LadderDimension {
|
|
625
|
+
readonly name: string;
|
|
626
|
+
/** What one unit of the dimension is, in plain words. */
|
|
627
|
+
readonly describe: string;
|
|
628
|
+
}
|
|
629
|
+
/** A budget on the median of each case, for example the time of a read. A record gives rounds and an A/A arm. */
|
|
630
|
+
interface MedianBudget {
|
|
631
|
+
readonly kind: "median";
|
|
632
|
+
readonly measure: string;
|
|
633
|
+
/** The unit of the limit and of the values. */
|
|
634
|
+
readonly unit: string;
|
|
635
|
+
/** The largest median that the budget permits. */
|
|
636
|
+
readonly limit: number;
|
|
637
|
+
/** The largest difference between the medians of the two arms. A larger difference makes the run too noisy. */
|
|
638
|
+
readonly maxDifference: number;
|
|
639
|
+
/** The level of the interval of each median. The default is 0.95. */
|
|
640
|
+
readonly caseLevel?: number;
|
|
641
|
+
}
|
|
642
|
+
/** A budget on the share of failed trials, for example failed requests. A record gives failures and trials. */
|
|
643
|
+
interface RateBudget {
|
|
644
|
+
readonly kind: "rate";
|
|
645
|
+
readonly measure: string;
|
|
646
|
+
/** The largest share of failures that the budget permits, from 0 to 1. */
|
|
647
|
+
readonly limit: number;
|
|
648
|
+
}
|
|
649
|
+
/** A budget on the largest value of a set of drills, for example the writes that a restore lost. One bad drill is `beyond`. */
|
|
650
|
+
interface WorstBudget {
|
|
651
|
+
readonly kind: "worst";
|
|
652
|
+
readonly measure: string;
|
|
653
|
+
readonly unit: string;
|
|
654
|
+
/** The largest value that the budget permits in any drill. */
|
|
655
|
+
readonly limit: number;
|
|
656
|
+
/** The number of drills that a verdict needs, 1 or more. With fewer, the budget is `cannot decide`. */
|
|
657
|
+
readonly minDrills: number;
|
|
658
|
+
}
|
|
659
|
+
/**
|
|
660
|
+
* A budget on a high quantile, for example the p99 of a read. A record gives the values. The verdict is the distribution-free
|
|
661
|
+
* interval of the quantile against the limit. A p99 needs 368 independent values at the level 0.95: refer to `quantileSamples`.
|
|
662
|
+
* Successive times of one run can follow each other. Space them apart, or give one value for each run.
|
|
663
|
+
*
|
|
664
|
+
* The evidence can also hold `censored`: a lower bound for each arrival with no reply, and for each arrival that was not
|
|
665
|
+
* sent. The bound is the time that the arrival waited. The true value is that bound or more, with no upper limit. Thus the
|
|
666
|
+
* low end of the interval reads the bounds, and the high end reads each censored value as `Infinity`. A `beyond` stays
|
|
667
|
+
* provable from the bounds alone. A `within` needs real replies up to the upper rank of the interval.
|
|
668
|
+
*/
|
|
669
|
+
interface QuantileBudget {
|
|
670
|
+
readonly kind: "quantile";
|
|
671
|
+
readonly measure: string;
|
|
672
|
+
/** The unit of the limit and of the values. */
|
|
673
|
+
readonly unit: string;
|
|
674
|
+
/** The quantile, more than 0 and less than 1, for example 0.99. */
|
|
675
|
+
readonly quantile: number;
|
|
676
|
+
/** The largest quantile that the budget permits. */
|
|
677
|
+
readonly limit: number;
|
|
678
|
+
/** The level of the interval. The default is 0.95. */
|
|
679
|
+
readonly level?: number;
|
|
680
|
+
}
|
|
681
|
+
/** One budget of a rung. */
|
|
682
|
+
type RungBudget = MedianBudget | QuantileBudget | RateBudget | WorstBudget;
|
|
683
|
+
/** One rung of a ladder. */
|
|
684
|
+
interface Rung {
|
|
685
|
+
/** The name of the rung, unique in the ladder. */
|
|
686
|
+
readonly name: string;
|
|
687
|
+
/** The size of the rung in each dimension that it names. */
|
|
688
|
+
readonly at: Readonly<Record<string, number>>;
|
|
689
|
+
readonly budgets: readonly RungBudget[];
|
|
690
|
+
/** The name of the automatic test that holds the rung. */
|
|
691
|
+
readonly test: string;
|
|
692
|
+
/** True when a gate holds the rung: the verdict fails when the rung is not `within`. */
|
|
693
|
+
readonly locked?: boolean;
|
|
694
|
+
}
|
|
695
|
+
/** The ladder of one subject. The rungs go from the smallest to the largest. */
|
|
696
|
+
interface Ladder {
|
|
697
|
+
readonly format: typeof LADDER_FORMAT;
|
|
698
|
+
/** The product or the service that the ladder is for. */
|
|
699
|
+
readonly subject: string;
|
|
700
|
+
readonly dimensions: readonly LadderDimension[];
|
|
701
|
+
readonly rungs: readonly Rung[];
|
|
702
|
+
}
|
|
703
|
+
/** The measured evidence for one budget. Its `kind` is the kind of the budget. */
|
|
704
|
+
type RungEvidence = {
|
|
705
|
+
readonly kind: "median";
|
|
706
|
+
readonly measure: string;
|
|
707
|
+
readonly rounds: readonly BudgetRound[];
|
|
708
|
+
readonly aa: readonly BudgetRound[];
|
|
709
|
+
} | {
|
|
710
|
+
readonly kind: "quantile";
|
|
711
|
+
readonly measure: string;
|
|
712
|
+
readonly values: readonly number[];
|
|
713
|
+
readonly censored?: readonly number[];
|
|
714
|
+
} | {
|
|
715
|
+
readonly kind: "rate";
|
|
716
|
+
readonly measure: string;
|
|
717
|
+
readonly failures: number;
|
|
718
|
+
readonly trials: number;
|
|
719
|
+
} | {
|
|
720
|
+
readonly kind: "worst";
|
|
721
|
+
readonly measure: string;
|
|
722
|
+
readonly values: readonly number[];
|
|
723
|
+
};
|
|
724
|
+
/** One run of the test of a rung. */
|
|
725
|
+
interface RungRecord {
|
|
726
|
+
/** The name of the rung. */
|
|
727
|
+
readonly rung: string;
|
|
728
|
+
/** The commit that the run measured. */
|
|
729
|
+
readonly commit: string;
|
|
730
|
+
/** The time of the run, as an ISO 8601 string. */
|
|
731
|
+
readonly at: string;
|
|
732
|
+
/** What the run did for real, for example "2 processes" or "a restore from a real backup". */
|
|
733
|
+
readonly real: readonly string[];
|
|
734
|
+
/** What the run made up, for example "90 % of the tenants as data at rest". An empty list states that nothing was synthetic. */
|
|
735
|
+
readonly synthetic: readonly string[];
|
|
736
|
+
readonly evidence: readonly RungEvidence[];
|
|
737
|
+
}
|
|
738
|
+
/** The verdict of one budget of a rung. */
|
|
739
|
+
interface BudgetResult {
|
|
740
|
+
readonly measure: string;
|
|
741
|
+
readonly outcome: BudgetOutcome;
|
|
742
|
+
/** The reason of the outcome, in one sentence, with the numbers. */
|
|
743
|
+
readonly reason: string;
|
|
744
|
+
}
|
|
745
|
+
/** The verdict of one rung. */
|
|
746
|
+
interface RungVerdict {
|
|
747
|
+
readonly rung: string;
|
|
748
|
+
readonly test: string;
|
|
749
|
+
readonly locked: boolean;
|
|
750
|
+
readonly outcome: BudgetOutcome;
|
|
751
|
+
/** The reason of the outcome, in one sentence. */
|
|
752
|
+
readonly reason: string;
|
|
753
|
+
readonly budgets: readonly BudgetResult[];
|
|
754
|
+
/** The commit of the record, or undefined when the rung has no record. */
|
|
755
|
+
readonly commit: string | undefined;
|
|
756
|
+
readonly real: readonly string[];
|
|
757
|
+
readonly synthetic: readonly string[];
|
|
758
|
+
}
|
|
759
|
+
/** The verdict of a ladder. */
|
|
760
|
+
interface LadderVerdict {
|
|
761
|
+
readonly subject: string;
|
|
762
|
+
/** The highest rung with each rung up to it `within`, or undefined when the first rung is not `within`. */
|
|
763
|
+
readonly held: string | undefined;
|
|
764
|
+
/** The first rung that is not `within`, or undefined when each rung is `within`. */
|
|
765
|
+
readonly next: string | undefined;
|
|
766
|
+
/** True when a locked rung is not `within`. A rung with no result is not held, so `cannot decide` fails too. */
|
|
767
|
+
readonly failed: boolean;
|
|
768
|
+
/** The reason of `failed`, in one sentence. */
|
|
769
|
+
readonly reason: string;
|
|
770
|
+
readonly rungs: readonly RungVerdict[];
|
|
771
|
+
}
|
|
772
|
+
/** The options of a ladder verdict. */
|
|
773
|
+
interface LadderOptions {
|
|
774
|
+
/** The time of the verdict, as an ISO 8601 string. It is an input, so that a verdict is the same at each read. */
|
|
775
|
+
readonly now: string;
|
|
776
|
+
/** The largest age of a record, in days. An older record gives `cannot decide`. The default accepts any age. */
|
|
777
|
+
readonly maxAgeDays?: number;
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* This function gives each problem of a ladder as data, or an empty list. A ladder needs a subject, one dimension or more,
|
|
781
|
+
* and one rung or more. Names are unique. Each rung names a test and has budgets. From one rung to the next, each dimension
|
|
782
|
+
* that the two rungs name grows.
|
|
783
|
+
*/
|
|
784
|
+
export declare function checkLadder(ladder: Ladder): readonly string[];
|
|
785
|
+
/** This function gives the verdict of one rung from its record. With no record, the rung is `cannot decide`. */
|
|
786
|
+
export declare function rungVerdict(rung: Rung, record: RungRecord | undefined, options: LadderOptions): RungVerdict;
|
|
787
|
+
/**
|
|
788
|
+
* This function gives the verdict of a ladder from the records of its rungs. It uses the newest record of each rung, so an
|
|
789
|
+
* older pass does not hide a newer failure. A rung high up does not count when a rung below it is not `within`. It throws
|
|
790
|
+
* a `RangeError` for a ladder with problems, because a verdict on a bad ladder has no meaning. See `checkLadder`.
|
|
791
|
+
*/
|
|
792
|
+
export declare function ladderVerdict(ladder: Ladder, records: readonly RungRecord[], options: LadderOptions): LadderVerdict;
|
|
793
|
+
/** The value at one rank of the ratios of one case, from the largest. */
|
|
794
|
+
interface CaseTail {
|
|
795
|
+
readonly case: string;
|
|
796
|
+
/** The value at the rank, or undefined when the rounds do not put the rank above the median. */
|
|
797
|
+
readonly tail: number | undefined;
|
|
798
|
+
readonly rounds: number;
|
|
799
|
+
}
|
|
800
|
+
/** The two limits of one case. */
|
|
801
|
+
interface TailLimit {
|
|
802
|
+
/** The largest median of the ratio `b / a` that the claim permits. */
|
|
803
|
+
readonly median: number;
|
|
804
|
+
/** The largest tail of the ratio `b / a` that the claim permits. */
|
|
805
|
+
readonly tail: number;
|
|
806
|
+
}
|
|
807
|
+
/** The options of `tailFalseFails`. */
|
|
808
|
+
interface TailRuleOptions {
|
|
809
|
+
/** The limits of all the cases, or a function that gives the limits of one case. */
|
|
810
|
+
readonly limit: TailLimit | ((caseName: string) => TailLimit);
|
|
811
|
+
/** The rank of the tail, from the largest. The default 2 reads the second largest ratio, so one slow process cannot move it. */
|
|
812
|
+
readonly rank?: number;
|
|
813
|
+
}
|
|
814
|
+
/** The options of a tail limit verdict. */
|
|
815
|
+
interface TailLimitOptions extends TailRuleOptions {
|
|
816
|
+
/**
|
|
817
|
+
* The largest tail of the A/A arm that lets a run decide. Each row under the tail of the A/A arm passes the tail limit, so
|
|
818
|
+
* a loud run has no power. This option has no default, because a run with no cap passes each row when it is loud.
|
|
819
|
+
*/
|
|
820
|
+
readonly aaCap: number;
|
|
821
|
+
/** The smallest number of A/A cases with a tail. The default is 5. */
|
|
822
|
+
readonly minimum?: number;
|
|
823
|
+
/**
|
|
824
|
+
* The names of the cases that the run must have. A case of this list with no record reads `cannot decide`. Without this
|
|
825
|
+
* option, the verdict reads only the cases of the candidate, so a run that loses a case can read `within`.
|
|
826
|
+
*/
|
|
827
|
+
readonly expected?: readonly string[];
|
|
828
|
+
}
|
|
829
|
+
/** The verdict of one case. */
|
|
830
|
+
interface CaseTailLimit extends CaseTail {
|
|
831
|
+
/** The median ratio of the case: the value `ratio` of `caseRatios`. The value is undefined when the case has no record. */
|
|
832
|
+
readonly ratio: number | undefined;
|
|
833
|
+
readonly limit: TailLimit;
|
|
834
|
+
/** The median is over its limit. */
|
|
835
|
+
readonly overMedian: boolean;
|
|
836
|
+
/** The tail is over its limit and over the tail of the A/A arm of the run. */
|
|
837
|
+
readonly overTail: boolean;
|
|
838
|
+
readonly outcome: LimitOutcome;
|
|
839
|
+
}
|
|
840
|
+
/** A case that an A/A arm cannot read, with the reason. */
|
|
841
|
+
interface TailGainCase {
|
|
842
|
+
readonly case: string;
|
|
843
|
+
/** The reason in one sentence. It names the limit under 1. */
|
|
844
|
+
readonly reason: string;
|
|
845
|
+
}
|
|
846
|
+
/** The result of `tailFalseFails`. */
|
|
847
|
+
interface TailFalseFails {
|
|
848
|
+
/** The cases that the rule fails on the A/A arm. Print the count of this list on the gate. */
|
|
849
|
+
readonly fails: readonly string[];
|
|
850
|
+
/** The cases with a limit under 1. These cases are not in `fails`, because an A/A pair shows no gain. */
|
|
851
|
+
readonly gains: readonly TailGainCase[];
|
|
852
|
+
}
|
|
853
|
+
/** A tail limit verdict, with the facts that it uses. */
|
|
854
|
+
interface TailLimitVerdict {
|
|
855
|
+
readonly outcome: LimitOutcome;
|
|
856
|
+
/** The reason of the outcome, in one sentence. */
|
|
857
|
+
readonly reason: string;
|
|
858
|
+
readonly cases: readonly CaseTailLimit[];
|
|
859
|
+
/** The largest tail over the cases of the A/A arm, or undefined when that arm has too few cases. */
|
|
860
|
+
readonly aaTail: number | undefined;
|
|
861
|
+
readonly aaCap: number;
|
|
862
|
+
readonly rank: number;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* This function gives the value at one rank of the ratios of each case, from the largest, in the order of `caseRatios`. It
|
|
866
|
+
* examines the records as `caseRatios` does. A case needs `2 * rank + 1` rounds, so that the value is above the median.
|
|
867
|
+
*/
|
|
868
|
+
export declare function caseTails(records: readonly PairedTime[], rank?: number): CaseTail[];
|
|
869
|
+
/**
|
|
870
|
+
* This function gives the verdict of the claim "the median and the tail of each case are at most their limits".
|
|
871
|
+
* - A case is `beyond` when its median is over its limit. It is also `beyond` when its tail is over its limit and over the
|
|
872
|
+
* largest tail of the A/A arm of the run.
|
|
873
|
+
* - A case with too few rounds for the rank is `cannot decide`, unless its median is over its limit.
|
|
874
|
+
* - A case of `expected` with no record is `cannot decide`.
|
|
875
|
+
* - The verdict is `beyond` when a case is `beyond`, and `within` when each case is `within`.
|
|
876
|
+
* - Each case and the verdict are `cannot decide` when the largest tail of the A/A arm is over `aaCap`. The same applies
|
|
877
|
+
* when the A/A arm has fewer than `minimum` cases with a tail. This is not a pass, so the caller takes another read.
|
|
878
|
+
*
|
|
879
|
+
* With the default rank, a real cost in 1 round cannot fail the tail limit, because 1 round cannot be told from noise. A
|
|
880
|
+
* cost in 2 rounds or more can fail it. The verdict has no interval, so a limit needs a margin from the spread of earlier
|
|
881
|
+
* runs.
|
|
882
|
+
*/
|
|
883
|
+
export declare function tailLimitVerdict(candidate: readonly PairedTime[], aa: readonly PairedTime[], options: TailLimitOptions): TailLimitVerdict;
|
|
884
|
+
/**
|
|
885
|
+
* This function applies the rule of `tailLimitVerdict` to each case of the A/A arm, and gives the cases that fail. Each
|
|
886
|
+
* case reads the tail of the other cases, because a case cannot be the noise of itself. An arm with one case gives no
|
|
887
|
+
* failed case.
|
|
888
|
+
*
|
|
889
|
+
* A limit under 1 states a gain, and an A/A pair shows no gain. So the A/A arm has no read of that case, and the case goes
|
|
890
|
+
* in `gains` with that reason. The tail of that case stays in the noise of the other cases. The false fails of a gain limit
|
|
891
|
+
* come from repeat reads of an unchanged tree against its fixed base.
|
|
892
|
+
*/
|
|
893
|
+
export declare function tailFalseFails(aa: readonly PairedTime[], options: TailRuleOptions): TailFalseFails;
|
|
701
894
|
/** One value of one measure, for one entry and one input. */
|
|
702
895
|
interface MeasureRow {
|
|
703
896
|
/** The name of the measure. */
|
|
@@ -980,5 +1173,5 @@ interface Rounds {
|
|
|
980
1173
|
* keeps the work.
|
|
981
1174
|
*/
|
|
982
1175
|
export declare function timeRounds(arms: Readonly<Record<Arm, () => number>>, options: RoundsOptions): Rounds;
|
|
983
|
-
export { type Arm, type Balanced, type Band, type BandKind, type BandOptions, type BudgetLook, type BudgetLooksOptions, type BudgetLooksVerdict, type BudgetMore, type BudgetOptions, type BudgetOutcome, type BudgetResult, type BudgetRound, type BudgetVerdict, type CaseBudget, type CaseInterval, type CaseLimit, type CaseRatio, type Comparison, type ControlFactors, type ControlOptions, type ControlRead, type ControlRow, type EntryCount, type GroupCounts, type GroupFactor, type GuardRead, type JobLimitVerdict, type JobRecords, type JobVerdict, type Ladder, type LadderDimension, type LadderOptions, type LadderVerdict, type LimitOptions, type LimitOutcome, type LimitVerdict, type MeasureCheck, type MeasureCheckOptions, type MeasureChecks, type MeasureFinding, type MeasureFindingKind, type MeasureRow, type MeasureRule, type MeasuredFactor, type MedianBudget, type NoControl, type NoFactor, type NoiseCheck, type PairedTime, type PartnerRead, type PoolFacts, type PoolOptions, type PooledJob, type PooledLimitVerdict, type PooledRecords, type PooledVerdict, type Power, type PowerOptions, type QuantileBudget, type RateBudget, type Rounds, type RoundsOptions, type RunPairs, type Rung, type RungBudget, type RungEvidence, type RungRecord, type RungVerdict, type SpreadRead, type TimeOutcome, type TimeVerdict, type VerdictOptions, type VerdictRule, type WinClaim, type WorstBudget, caseRatios, checkPairedTime, firstArm };
|
|
1176
|
+
export { type Arm, type Balanced, type Band, type BandKind, type BandOptions, type BudgetLook, type BudgetLooksOptions, type BudgetLooksVerdict, type BudgetMore, type BudgetOptions, type BudgetOutcome, type BudgetResult, type BudgetRound, type BudgetVerdict, type CaseBudget, type CaseGate, type CaseInterval, type CaseLimit, type CaseRatio, type CaseTail, type CaseTailLimit, type Comparison, type ControlFactors, type ControlOptions, type ControlRead, type ControlRow, type EntryCount, type Gate, type GateCaseOutcome, type GateJobRead, type GateOutcome, type GroupCounts, type GroupFactor, type GuardRead, type JobLimitVerdict, type JobRecords, type JobVerdict, type Ladder, type LadderDimension, type LadderOptions, type LadderVerdict, type LimitOptions, type LimitOutcome, type LimitVerdict, type MeasureCheck, type MeasureCheckOptions, type MeasureChecks, type MeasureFinding, type MeasureFindingKind, type MeasureRow, type MeasureRule, type MeasuredFactor, type MedianBudget, type NoControl, type NoFactor, type NoiseCheck, type NotSlowerOptions, type NotSlowerRead, type NotSlowerVerdict, type PairedTime, type PartnerRead, type PoolFacts, type PoolOptions, type PooledJob, type PooledLimitVerdict, type PooledRecords, type PooledVerdict, type Power, type PowerOptions, type QuantileBudget, type RateBudget, type Rounds, type RoundsOptions, type RunPairs, type Rung, type RungBudget, type RungEvidence, type RungRecord, type RungVerdict, type SpreadRead, type TailFalseFails, type TailGainCase, type TailLimit, type TailLimitOptions, type TailLimitVerdict, type TailRuleOptions, type TimeOutcome, type TimeVerdict, type VerdictOptions, type VerdictRule, type WinClaim, type WorstBudget, caseRatios, checkPairedTime, firstArm };
|
|
984
1177
|
//# sourceMappingURL=index.d.ts.map
|