import { bitFlag } from '../src/lib/bitflag';
import { createBitFlagsEnum } from '../src/lib/bitflag_classes';
var groupByName = function (xs: [string, number][]): Record<string, number[]> {
return xs.reduce((rv, x) => {
(rv[x[0]] = rv[x[0]] || []).push(x[1]);
return rv;
}, {});
};
const testGroup = (
name: string,
desiredRuns: number,
testFns: [string, () => number][]
) => {
const results: [string, number][] = [];
for (let i = 0; i < desiredRuns; i++) {
results.push(
...testFns.map<[string, number]>(([name, fn]) => [name, fn()])
);
}
const groupedResults = groupByName(results);
console.group(`--- ${name} ---`);
Object.entries(groupedResults).forEach(([name, times]) => {
const avgTime = times.reduce((sum, cur) => sum + cur / times.length);
console.log(name, avgTime);
});
console.groupEnd();
};
const test = (iterations: number, fn: (i: number) => void): number => {
let time = 0;
const start = performance.now();
for (let i = 0; i < iterations; i++) {
fn(i);
}
time += performance.now() - start;
return time;
};
const native_bf_setup_3 = () => {
enum Perms {
Read = 1 << 1,
Write = 1 << 2,
Execute = 1 << 3,
}
return Perms;
};
const bitflags_setup_3 = () => {
return bitFlag('Read', 'Write', 'Execute');
};
const bitflags_classes_setup_3 = () => {
return createBitFlagsEnum(['Read', 'Write', 'Execute'] as const);
};
const array_setup_3 = () => {
return ['Read', 'Write', 'Execute'];
};
const iterations = 1000000;
// expected order (fast to slow): array_setup_3, bitflags_setup_3, bitflags_classes_setup_3
testGroup("Setup/Create 'Enum'", 10, [
['native_bf_setup_3', () => test(iterations, native_bf_setup_3)],
['bitflags_setup_3', () => test(iterations, bitflags_setup_3)],
[
'bitflags_classes_setup_3',
() => test(iterations, bitflags_classes_setup_3),
],
['array_setup_3', () => test(iterations, array_setup_3)],
]);
{
// Create Union
enum native_perms_enum {
Read = 1 << 1,
Write = 1 << 2,
Execute = 1 << 3,
}
const native_bf = () => {
return (
native_perms_enum.Read |
native_perms_enum.Write |
native_perms_enum.Execute
);
};
const bitflags_match_3_enum = bitFlag('Read', 'Write', 'Execute');
const bitflags = () => {
return bitflags_match_3_enum.union(
bitflags_match_3_enum.Read,
bitflags_match_3_enum.Write,
bitflags_match_3_enum.Execute
);
};
const bitflags_classes_3_enum = createBitFlagsEnum([
'Read',
'Write',
'Execute',
] as const);
const bitflags_classes_or = () => {
return bitflags_classes_3_enum.Execute.or(bitflags_classes_3_enum.Read).or(
bitflags_classes_3_enum.Write
);
};
const bitflags_classes_union = () => {
return bitflags_classes_3_enum.Execute.union([
bitflags_classes_3_enum.Read,
bitflags_classes_3_enum.Write,
]);
};
const array_3_val = ['Read', 'Write', 'Execute'];
const array = () => {
return ['Read', 'Write', 'Execute'];
};
testGroup('Create a size-3 Union', 10, [
['native_bf', () => test(iterations, native_bf)],
['bitflags', () => test(iterations, bitflags)],
['bitflags_classes_or', () => test(iterations, bitflags_classes_or)],
['bitflags_classes_union', () => test(iterations, bitflags_classes_union)],
['array', () => test(iterations, array)],
]);
}
// expected order (fast to slow): bitflags_match_3, bitflags_classes_match_3, array_match_3
enum native_perms_enum {
Read = 1 << 1,
Write = 1 << 2,
Execute = 1 << 3,
}
const native_perms_3_val =
native_perms_enum.Read | native_perms_enum.Write | native_perms_enum.Execute;
const native_bf_match_3 = () => {
return (native_perms_3_val & bitflags_match_3_enum.Execute) !== 0;
};
const bitflags_match_3_enum = bitFlag('Read', 'Write', 'Execute');
const bitflags_match_3_val = bitflags_match_3_enum.union(
bitflags_match_3_enum.Read,
bitflags_match_3_enum.Write,
bitflags_match_3_enum.Execute
);
const bitflags_match_3 = () => {
return bitflags_match_3_val.hasFlag(bitflags_match_3_enum.Execute);
};
const bitflags_classes_3_enum = createBitFlagsEnum([
'Read',
'Write',
'Execute',
] as const);
const bitflags_classes_3_val = bitflags_classes_3_enum.Execute.or(
bitflags_classes_3_enum.Read
).or(bitflags_classes_3_enum.Write);
const bitflags_classes_match_3 = () => {
return bitflags_classes_3_val.hasFlag(bitflags_classes_3_enum.Execute);
};
const array_3_val = ['Read', 'Write', 'Execute'];
const array_match_3 = () => {
return array_3_val.includes('Execute');
};
testGroup('Match a Single Flag in size-3 Union', 10, [
['native_bf_match_3', () => test(iterations, native_bf_match_3)],
['bitflags_match_3', () => test(iterations, bitflags_match_3)],
[
'bitflags_classes_match_3',
() => test(iterations, bitflags_classes_match_3),
],
['array_match_3', () => test(iterations, array_match_3)],
]);