David Sehnal há 7 anos atrás
pai
commit
cd246b25d6
2 ficheiros alterados com 111 adições e 0 exclusões
  1. 33 0
      src/mol-base/collections/column.ts
  2. 78 0
      src/perf-tests/column.ts

+ 33 - 0
src/mol-base/collections/column.ts

@@ -35,6 +35,13 @@ namespace Column {
         end?: number
     }
 
+    export interface LambdaSpec<T extends Type> {
+        value: (row: number) => T['@type'],
+        rowCount: number,
+        type: T,
+        valueKind?: (row: number) => ValueKind,
+    }
+
     export interface ArraySpec<T extends Type> {
         array: ArrayLike<T['@type']>,
         type: T,
@@ -51,6 +58,10 @@ namespace Column {
         return constColumn(v, rowCount, type, ValueKind.Present);
     }
 
+    export function ofLambda<T extends Type>(spec: LambdaSpec<T>): Column<T['@type']> {
+        return lambdaColumn(spec);
+    }
+
     export function ofArray<T extends Column.Type>(spec: Column.ArraySpec<T>): Column<T['@type']> {
         return arrayColumn(spec);
     }
@@ -92,6 +103,28 @@ function constColumn<T extends Column.Type>(v: T['@type'], rowCount: number, typ
     }
 }
 
+function lambdaColumn<T extends Column.Type>({ value, valueKind, rowCount, type }: Column.LambdaSpec<T>): Column<T['@type']> {
+    return {
+        '@type': type,
+        '@array': void 0,
+        isDefined: true,
+        rowCount,
+        value,
+        valueKind: valueKind ? valueKind : row => Column.ValueKind.Present,
+        toArray: params => {
+            const { array, start } = createArray(rowCount, params);
+            for (let i = 0, _i = array.length; i < _i; i++) array[i] = value(i + start);
+            return array;
+        },
+        stringEquals: type.kind === 'str'
+            ? (row, v) => value(row) === v
+            : type.kind === 'float' || type.kind === 'int'
+            ? (row, v) => value(row) === +v
+            : (row, value) => false,
+        areValuesEqual: (rowA, rowB) => value(rowA) === value(rowB)
+    }
+}
+
 function arrayColumn<T extends Column.Type>({ array, type, valueKind }: Column.ArraySpec<T>): Column<T['@type']> {
     const rowCount = array.length;
     const value: Column<T['@type']>['value'] = type.kind === 'str'

+ 78 - 0
src/perf-tests/column.ts

@@ -0,0 +1,78 @@
+import * as B from 'benchmark'
+import C from '../mol-base/collections/column'
+
+export namespace Column {
+    function createData(n: number) {
+        const ret = new Float32Array(n);
+        for (let i = 0; i < n; i++) {
+            ret[i] = i * i + 1;
+        }
+        return ret;
+    }
+
+    function raw(xs: ArrayLike<number>) {
+        let sum = 0;
+        for (let i = 0, _i = xs.length; i < _i; i++) {
+            sum += xs[i];
+        }
+        return sum;
+    }
+
+    function column(col: C<number>) {
+        let sum = 0;
+        for (let i = 0, _i = col.rowCount; i < _i; i++) {
+            sum += col.value(i);
+        }
+        return sum;
+    }
+
+    function column1(col: C<number>) {
+        let sum = 0;
+        for (let i = 0, _i = col.rowCount; i < _i; i++) {
+            sum += col.value(i);
+        }
+        return sum;
+    }
+
+    function val(i: number) { return i * i + 1; }
+
+    export function runMono() {
+        const suite = new B.Suite();
+        const data = createData(1000);
+        const nativeData = [...data as any];
+        const col = C.ofArray({ array: data, type: C.Type.float });
+        const lambda = C.ofLambda({ value: val, rowCount: data.length, type: C.Type.float });
+        const cnst = C.ofConst(10, data.length, C.Type.float);
+        suite
+            .add('raw', () => raw(data))
+            .add('native raw', () => raw(nativeData))
+            .add('arraycol', () => column(col))
+            .add('arraycol1', () => column(col))
+            .add('const', () => column1(cnst))
+            .add('arraycol2', () => column(col))
+            .add('lambda', () => column1(lambda))
+            .on('cycle', (e: any) => console.log(String(e.target)))
+            .run();
+    }
+
+    export function runPoly() {
+        const suite = new B.Suite();
+        const data = createData(10000);
+        const nativeData = [...data as any];
+        const col = C.ofArray({ array: data, type: C.Type.float });
+        const lambda = C.ofLambda({ value: val, rowCount: data.length, type: C.Type.float });
+        const cnst = C.ofConst(10, data.length, C.Type.float);
+        suite
+            .add('raw', () => raw(data))
+            .add('native raw', () => raw(nativeData))
+            .add('arraycol', () => column(col))
+            .add('const', () => column(cnst))
+            .add('arraycol2', () => column(col))
+            .add('lambda', () => column(lambda))
+            .on('cycle', (e: any) => console.log(String(e.target)))
+            .run();
+    }
+}
+
+Column.runMono();
+Column.runPoly();