diff --git a/src/mol-model/structure/query.ts b/src/mol-model/structure/query.ts index e4f3190a4303e31567ba5b95d81369ef5ad1c93e..775112fbc134d27d7e75f9de26952be6b58a4e80 100644 --- a/src/mol-model/structure/query.ts +++ b/src/mol-model/structure/query.ts @@ -7,8 +7,8 @@ import { StructureSelection } from './query/selection' import { StructureQuery } from './query/query' export * from './query/context' -import * as generators from './query/generators' -import * as modifiers from './query/modifiers' +import * as generators from './query/queries/generators' +import * as modifiers from './query/queries/modifiers' import pred from './query/predicates' export const Queries = { diff --git a/src/mol-model/structure/query/context.ts b/src/mol-model/structure/query/context.ts index eedd8d3e3988679615591e243846dee69b51a287..5c94becb65d8436d1b39a43c7d451b85a25d8ed6 100644 --- a/src/mol-model/structure/query/context.ts +++ b/src/mol-model/structure/query/context.ts @@ -9,16 +9,19 @@ import { Structure, StructureElement } from '../structure'; export interface QueryContextView { readonly element: StructureElement; + readonly currentStructure: Structure; } export class QueryContext implements QueryContextView { private currentStack: StructureElement[] = []; + private currentLocked = false; - readonly structure: Structure; + readonly inputStructure: Structure; readonly taskCtx: RuntimeContext; /** Current element */ readonly element: StructureElement = StructureElement.create(); + readonly currentStructure: Structure = void 0 as any; pushCurrentElement(): StructureElement { this.currentStack[this.currentStack.length] = this.element; @@ -30,8 +33,19 @@ export class QueryContext implements QueryContextView { (this.element as StructureElement) = this.currentStack.pop()!; } + lockCurrentStructure(structure: Structure) { + if (this.currentLocked) throw new Error('Current structure already locked.'); + this.currentLocked = true; + (this.currentStructure as Structure) = structure; + } + + unlockCurrentStructure() { + this.currentLocked = false; + (this.currentStructure as any) = void 0; + } + constructor(structure: Structure, taskCtx: RuntimeContext) { - this.structure = structure; + this.inputStructure = structure; this.taskCtx = taskCtx; } } diff --git a/src/mol-model/structure/query/queries/combinators.ts b/src/mol-model/structure/query/queries/combinators.ts new file mode 100644 index 0000000000000000000000000000000000000000..de7200ac124b2b8c537df63caa1a7a5fc88cd179 --- /dev/null +++ b/src/mol-model/structure/query/queries/combinators.ts @@ -0,0 +1,5 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ diff --git a/src/mol-model/structure/query/queries/filters.ts b/src/mol-model/structure/query/queries/filters.ts new file mode 100644 index 0000000000000000000000000000000000000000..9bd5a50d2b07c295bcb58f33086ab41ac370e2f6 --- /dev/null +++ b/src/mol-model/structure/query/queries/filters.ts @@ -0,0 +1,41 @@ +/** + * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info. + * + * @author David Sehnal <david.sehnal@gmail.com> + */ + +// import { StructureQuery } from '../query' +// import { StructureSelection } from '../selection' +// import { Unit, StructureProperties as P, Structure } from '../../structure' +// import { Segmentation, SortedArray } from 'mol-data/int' +// import { LinearGroupingBuilder } from '../utils/builders'; +// import { QueryPredicate, QueryFn, QueryContextView } from '../context'; + +// export function pick(query: StructureQuery, pred: QueryPredicate): StructureQuery { +// return async ctx => { +// const sel = await query(ctx); + +// if (StructureSelection.isSingleton(sel)) { +// const ret = StructureSelection.LinearBuilder(ctx.inputStructure); +// for (const unit of ctx.inputStructure.units) { +// const { elements } = unit; +// for (let i = 0, _i = elements.length; i < _i; i++) { +// // TODO: optimize this somehow??? +// const s = Structure.create([unit.getChild(SortedArray.ofSingleton(elements[i]))]); +// ctx.lockCurrentStructure(s); +// if (pred(ctx)) ret.add(s); +// ctx.unlockCurrentStructure(); +// } +// } +// return ret.getSelection(); +// } else { +// const ret = StructureSelection.LinearBuilder(ctx.inputStructure); +// for (const s of sel.structures) { +// ctx.lockCurrentStructure(s); +// if (pred(ctx)) ret.add(s); +// ctx.unlockCurrentStructure(); +// } +// return ret.getSelection(); +// } +// }; +// } diff --git a/src/mol-model/structure/query/generators.ts b/src/mol-model/structure/query/queries/generators.ts similarity index 86% rename from src/mol-model/structure/query/generators.ts rename to src/mol-model/structure/query/queries/generators.ts index 01f16cccb7a0b3cb76c33cfeaf1e0351be8206f0..8454c781fc7ff6b6c28ca5d4c4b456f136eac0e4 100644 --- a/src/mol-model/structure/query/generators.ts +++ b/src/mol-model/structure/query/queries/generators.ts @@ -4,14 +4,14 @@ * @author David Sehnal <david.sehnal@gmail.com> */ -import { StructureQuery } from './query' -import { StructureSelection } from './selection' -import { Unit, StructureProperties as P } from '../structure' +import { StructureQuery } from '../query' +import { StructureSelection } from '../selection' +import { Unit, StructureProperties as P } from '../../structure' import { Segmentation } from 'mol-data/int' -import { LinearGroupingBuilder } from './utils/builders'; -import { QueryPredicate, QueryFn, QueryContextView } from './context'; +import { LinearGroupingBuilder } from '../utils/builders'; +import { QueryPredicate, QueryFn, QueryContextView } from '../context'; -export const all: StructureQuery = async (ctx) => StructureSelection.Singletons(ctx.structure, ctx.structure); +export const all: StructureQuery = async (ctx) => StructureSelection.Singletons(ctx.inputStructure, ctx.inputStructure); export interface AtomsQueryParams { entityTest: QueryPredicate, @@ -45,10 +45,10 @@ export function atoms(params?: Partial<AtomsQueryParams>): StructureQuery { function atomGroupsLinear(atomTest: QueryPredicate): StructureQuery { return async (ctx) => { - const { structure } = ctx; - const { units } = structure; + const { inputStructure } = ctx; + const { units } = inputStructure; const l = ctx.pushCurrentElement(); - const builder = structure.subsetBuilder(true); + const builder = inputStructure.subsetBuilder(true); let progress = 0; for (const unit of units) { @@ -66,16 +66,16 @@ function atomGroupsLinear(atomTest: QueryPredicate): StructureQuery { if (ctx.taskCtx.shouldUpdate) await ctx.taskCtx.update({ message: 'Atom Groups', current: progress, max: units.length }); } ctx.popCurrentElement(); - return StructureSelection.Singletons(structure, builder.getStructure()); + return StructureSelection.Singletons(inputStructure, builder.getStructure()); }; } function atomGroupsSegmented({ entityTest, chainTest, residueTest, atomTest }: AtomsQueryParams): StructureQuery { return async (ctx) => { - const { structure } = ctx; - const { units } = structure; + const { inputStructure } = ctx; + const { units } = inputStructure; const l = ctx.pushCurrentElement(); - const builder = structure.subsetBuilder(true); + const builder = inputStructure.subsetBuilder(true); let progress = 0; for (const unit of units) { @@ -115,16 +115,16 @@ function atomGroupsSegmented({ entityTest, chainTest, residueTest, atomTest }: A if (ctx.taskCtx.shouldUpdate) await ctx.taskCtx.update({ message: 'Atom Groups', current: progress, max: units.length }); } ctx.popCurrentElement(); - return StructureSelection.Singletons(structure, builder.getStructure()); + return StructureSelection.Singletons(inputStructure, builder.getStructure()); }; } function atomGroupsGrouped({ entityTest, chainTest, residueTest, atomTest, groupBy }: AtomsQueryParams): StructureQuery { return async (ctx) => { - const { structure } = ctx; - const { units } = structure; + const { inputStructure } = ctx; + const { units } = inputStructure; const l = ctx.pushCurrentElement(); - const builder = new LinearGroupingBuilder(structure); + const builder = new LinearGroupingBuilder(inputStructure); let progress = 0; for (const unit of units) { diff --git a/src/mol-model/structure/query/modifiers.ts b/src/mol-model/structure/query/queries/modifiers.ts similarity index 79% rename from src/mol-model/structure/query/modifiers.ts rename to src/mol-model/structure/query/queries/modifiers.ts index 42dea2f05450b2dc419c5b2dcafd4587c9e75ccb..7943e9e7f954b176cb4d612bf3906df16ae09168 100644 --- a/src/mol-model/structure/query/modifiers.ts +++ b/src/mol-model/structure/query/queries/modifiers.ts @@ -6,11 +6,11 @@ import { Segmentation } from 'mol-data/int'; import { RuntimeContext } from 'mol-task'; -import { Structure, Unit } from '../structure'; -import { StructureQuery } from './query'; -import { StructureSelection } from './selection'; -import { UniqueStructuresBuilder } from './utils/builders'; -import { StructureUniqueSubsetBuilder } from '../structure/util/unique-subset-builder'; +import { Structure, Unit } from '../../structure'; +import { StructureQuery } from '../query'; +import { StructureSelection } from '../selection'; +import { UniqueStructuresBuilder } from '../utils/builders'; +import { StructureUniqueSubsetBuilder } from '../../structure/util/unique-subset-builder'; function getWholeResidues(ctx: RuntimeContext, source: Structure, structure: Structure) { const builder = source.subsetBuilder(true); @@ -41,12 +41,12 @@ export function wholeResidues(query: StructureQuery, isFlat: boolean): Structure return async (ctx) => { const inner = await query(ctx); if (StructureSelection.isSingleton(inner)) { - return StructureSelection.Singletons(ctx.structure, getWholeResidues(ctx.taskCtx, ctx.structure, inner.structure)); + return StructureSelection.Singletons(ctx.inputStructure, getWholeResidues(ctx.taskCtx, ctx.inputStructure, inner.structure)); } else { - const builder = new UniqueStructuresBuilder(ctx.structure); + const builder = new UniqueStructuresBuilder(ctx.inputStructure); let progress = 0; for (const s of inner.structures) { - builder.add(getWholeResidues(ctx.taskCtx, ctx.structure, s)); + builder.add(getWholeResidues(ctx.taskCtx, ctx.inputStructure, s)); progress++; if (ctx.taskCtx.shouldUpdate) await ctx.taskCtx.update({ message: 'Whole Residues', current: progress, max: inner.structures.length }); } @@ -87,13 +87,13 @@ export function includeSurroundings(query: StructureQuery, params: IncludeSurrou return async (ctx) => { const inner = await query(ctx); if (StructureSelection.isSingleton(inner)) { - const surr = await getIncludeSurroundings(ctx.taskCtx, ctx.structure, inner.structure, params); - const ret = StructureSelection.Singletons(ctx.structure, surr); + const surr = await getIncludeSurroundings(ctx.taskCtx, ctx.inputStructure, inner.structure, params); + const ret = StructureSelection.Singletons(ctx.inputStructure, surr); return ret; } else { - const builder = new UniqueStructuresBuilder(ctx.structure); + const builder = new UniqueStructuresBuilder(ctx.inputStructure); for (const s of inner.structures) { - builder.add(await getIncludeSurroundings(ctx.taskCtx, ctx.structure, s, params)); + builder.add(await getIncludeSurroundings(ctx.taskCtx, ctx.inputStructure, s, params)); } return builder.getSelection(); } diff --git a/src/perf-tests/tasks.ts b/src/perf-tests/tasks.ts index c1fa6c9c9d8111cadf33caf600c056e566f3926c..f0c0eb86b3e5948fa3cd061f4bb0c697f861b0ee 100644 --- a/src/perf-tests/tasks.ts +++ b/src/perf-tests/tasks.ts @@ -98,20 +98,80 @@ export namespace Tasks { .on('cycle', (e: any) => console.log(String(e.target))) .run(); } + + function add(x: number, y: number) { + return x + y; + } + + // async function addAs(x: number, y: number) { + // return x + y; + // } + + async function opAsync(n: number) { + let ret = 0; + for (let i = 0; i < n; i++) { + const v = add(i, i + 1); + ret += (v as any).then ? await v : v; + } + return ret; + } + + function opNormal(n: number) { + let ret = 0; + for (let i = 0; i < n; i++) { + ret += add(i, i + 1); + } + return ret; + } + + export async function awaitF() { + const N = 10000000; + + console.time('async'); + console.log(await opAsync(N)); + console.timeEnd('async'); + + console.time('async'); + console.log(await opAsync(N)); + console.timeEnd('async'); + + console.time('async'); + console.log(await opAsync(N)); + console.timeEnd('async'); + + console.time('normal'); + console.log(opNormal(N)); + console.timeEnd('normal'); + console.time('normal'); + console.log(opNormal(N)); + console.timeEnd('normal'); + console.time('normal'); + console.log(opNormal(N)); + console.timeEnd('normal'); + + // const suite = new B.Suite(); + // suite + // .add(`async`, async () => { return await opAsync(100000); }) + // .add(`normal`, () => { return opNormal(100000); }) + // .on('cycle', (e: any) => console.log(String(e.target))) + // .run(); + } } (async function() { // await Tasks.testImmediate(); // await Tasks.testImmediate(); - await Tasks.baseline(); - await Tasks.yielding(); - await Tasks.yielding1(); - await Tasks.testYielding(); - await Tasks.baseline(); - await Tasks.yielding(); - await Tasks.yielding1(); - await Tasks.testYielding(); + // await Tasks.baseline(); + // await Tasks.yielding(); + // await Tasks.yielding1(); + // await Tasks.testYielding(); + // await Tasks.baseline(); + // await Tasks.yielding(); + // await Tasks.yielding1(); + // await Tasks.testYielding(); + + await Tasks.awaitF(); }()) // console.time('test')