Performance work, plus fix #405 (#406)

* remove memoization

* update to flash 1.0.2; turn on threading

* stand-alone helper routines for array slicing

* fix issue #405

* reset diffexp state when world changes

* performance work in dimension creation; fix world slicing bug

* update tests to match new state mgmt api

* update flask

* do not make dimensions for useless annotations

* update test to match optimizations
This commit is contained in:
Bruce Martin
2018-11-05 13:57:58 -08:00
committed by GitHub
parent 24a8a23355
commit 2d5bc9d0c9
10 changed files with 246 additions and 97 deletions
@@ -77,7 +77,8 @@ describe("createWorldFromEntireUniverse", () => {
varDataCache: expect.any(Object),
worldObsIndex: null // indicating full universe
obsIndex: null, // null indicating full universe
obsBackIndex: null
})
);
});
@@ -120,16 +121,21 @@ describe("createWorldFromCurrentSelection", () => {
nObs: universeIndices.length,
obsAnnotations: _.map(universeIndices, i => universe.obsAnnotations[i]),
obsLayout: {
X: _.map(universeIndices, i => universe.obsLayout.X[i]),
Y: _.map(universeIndices, i => universe.obsLayout.Y[i])
X: new Float32Array(
_.map(universeIndices, i => universe.obsLayout.X[i])
),
Y: new Float32Array(
_.map(universeIndices, i => universe.obsLayout.Y[i])
)
},
worldObsIndex: _.transform(
obsBackIndex: _.transform(
universeIndices,
(result, univIdx, worldIdx) => {
result[univIdx] = worldIdx;
},
new Array(universe.nObs).fill(-1)
)
new Uint32Array(universe.nObs).fill(-1)
),
obsIndex: new Uint32Array(universeIndices)
};
expect(world).toMatchObject(
@@ -141,9 +147,13 @@ describe("createWorldFromCurrentSelection", () => {
obsAnnotations: expected.obsAnnotations,
varAnnotations: universe.varAnnotations,
obsLayout: expected.obsLayout,
summary: expect.any(Object) /* we could do better! */,
summary: {
obs: expect.any(Object) /* we could do better! */,
var: expect.any(Object) /* we could do better! */
},
varDataCache: expect.any(Object),
worldObsIndex: expected.worldObsIndex
obsIndex: expected.obsIndex,
obsBackIndex: expected.obsBackIndex
})
);
});
@@ -163,11 +173,15 @@ describe("createObsDimensionMap", () => {
expect(dimensionMap).toBeDefined();
REST.annotationsObs.names.forEach(name => {
const dim = dimensionMap[obsAnnoDimensionName(name)];
const { type } = schemaByObsName[name];
if (type === "string" || type === "boolean" || type === "categorical") {
expect(dim).toBeInstanceOf(Crossfilter.EnumDimension);
if (name === "name") {
expect(dim).toBeUndefined();
} else {
expect(dim).toBeInstanceOf(Crossfilter.ScalarDimension);
const { type } = schemaByObsName[name];
if (type === "string" || type === "boolean" || type === "categorical") {
expect(dim).toBeInstanceOf(Crossfilter.EnumDimension);
} else {
expect(dim).toBeInstanceOf(Crossfilter.ScalarDimension);
}
}
});
expect(dimensionMap[layoutDimensionName("X")]).toBeInstanceOf(
@@ -205,6 +219,7 @@ describe("subsetVarData", () => {
world,
crossfilter
);
expect(newWorld.obsIndex).toMatchObject(new Uint32Array([0, 2]));
/* expect a subset */
const result = World.subsetVarData(newWorld, universe, sourceVarData);
@@ -0,0 +1,115 @@
import {
fillRange,
sliceByIndex,
makeSortIndex,
lowerBound,
lowerBoundIndirect,
upperBoundIndirect
} from "../../../src/util/typedCrossfilter/util";
describe("fillRange", () => {
test("Array", () => {
expect(fillRange(new Array(6))).toMatchObject([0, 1, 2, 3, 4, 5]);
expect(fillRange(new Array(4), 1)).toMatchObject([1, 2, 3, 4]);
expect(fillRange([])).toMatchObject([]);
});
test("Uint32Array", () => {
expect(fillRange(new Uint32Array(6))).toMatchObject(
new Uint32Array([0, 1, 2, 3, 4, 5])
);
expect(fillRange(new Array(4), 1)).toMatchObject(
new Uint32Array([1, 2, 3, 4])
);
expect(fillRange([])).toMatchObject(new Uint32Array([]));
});
});
describe("sliceByIndex", () => {
test("Array", () => {
expect(sliceByIndex([0, 1, 2, 3, 4], [0, 1, 2])).toMatchObject([0, 1, 2]);
expect(sliceByIndex([0, 1, 2, 3, 4], [2, 1, 0])).toMatchObject([2, 1, 0]);
expect(sliceByIndex([0, 1, 2, 3, 4], [])).toMatchObject([]);
expect(sliceByIndex([], [])).toMatchObject([]);
});
test("Uint32Array", () => {
expect(
sliceByIndex([0, 1, 2, 3, 4], new Uint32Array([0, 1, 2]))
).toMatchObject([0, 1, 2]);
expect(
sliceByIndex([0, 1, 2, 3, 4], new Uint32Array([2, 1, 0]))
).toMatchObject([2, 1, 0]);
expect(sliceByIndex([0, 1, 2, 3, 4], new Uint32Array([]))).toMatchObject(
[]
);
expect(sliceByIndex([], new Uint32Array([]))).toMatchObject([]);
expect(
sliceByIndex(new Uint32Array([0, 1, 2, 3, 4]), new Uint32Array([0, 1, 2]))
).toMatchObject(new Uint32Array([0, 1, 2]));
expect(
sliceByIndex(new Uint32Array([0, 1, 2, 3, 4]), new Uint32Array([2, 1, 0]))
).toMatchObject(new Uint32Array([2, 1, 0]));
expect(
sliceByIndex(
new Uint32Array([0, 1, 2, 3, 4]),
new Uint32Array(new Uint32Array([]))
)
).toMatchObject(new Uint32Array([]));
expect(
sliceByIndex(new Uint32Array([]), new Uint32Array([]))
).toMatchObject(new Uint32Array([]));
});
test("Float32Array", () => {
expect(
sliceByIndex(new Float32Array([0, 1, 2, 3, 4]), [0, 1, 2])
).toMatchObject(new Float32Array([0, 1, 2]));
expect(
sliceByIndex(new Float32Array([0, 1, 2, 3, 4]), [2, 1, 0])
).toMatchObject(new Float32Array([2, 1, 0]));
expect(sliceByIndex(new Float32Array([0, 1, 2, 3, 4]), [])).toMatchObject(
new Float32Array([])
);
expect(sliceByIndex(new Float32Array([]), [])).toMatchObject(
new Float32Array([])
);
});
});
describe("makeSortIndex", () => {
test("Array", () => {
expect(makeSortIndex([3, 2, 1, 0])).toMatchObject(
new Uint32Array([3, 2, 1, 0])
);
expect(makeSortIndex([3, 2, 1, 0, 4])).toMatchObject(
new Uint32Array([3, 2, 1, 0, 4])
);
expect(makeSortIndex([])).toMatchObject(new Uint32Array([]));
});
test("Float32Array", () => {
expect(makeSortIndex(new Float32Array([3, 2, 1, 0]))).toMatchObject(
new Uint32Array([3, 2, 1, 0])
);
expect(makeSortIndex(new Float32Array([3, 2, 1, 0, 4]))).toMatchObject(
new Uint32Array([3, 2, 1, 0, 4])
);
expect(makeSortIndex(new Float32Array([]))).toMatchObject(
new Uint32Array([])
);
});
test("Int32Array", () => {
expect(makeSortIndex(new Int32Array([3, 2, 1, 0]))).toMatchObject(
new Uint32Array([3, 2, 1, 0])
);
expect(makeSortIndex(new Int32Array([3, 2, 1, 0, 4]))).toMatchObject(
new Uint32Array([3, 2, 1, 0, 4])
);
expect(makeSortIndex(new Int32Array([]))).toMatchObject(
new Uint32Array([])
);
});
});