-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
11897c3
commit 184d3a5
Showing
10 changed files
with
425 additions
and
300 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import { bench, boxplot, group, run, summary } from "mitata"; | ||
import { compose } from "./fixpoint.ts"; | ||
import { aaa } from "./functions.ts"; | ||
|
||
const EMPTYUI8 = new Uint8Array([1, 2, 3]); | ||
|
||
const f = aaa.f; | ||
|
||
const { termminate, resolver } = compose({ | ||
threads: 1, | ||
})({ | ||
aaa, | ||
}); | ||
|
||
boxplot(async () => { | ||
group("5", () => { | ||
summary(() => { | ||
bench("main * 5", async () => { | ||
await f(EMPTYUI8), await f(EMPTYUI8); | ||
}); | ||
|
||
bench(" 5 thread ", async () => { | ||
await resolver.aaa(EMPTYUI8), await resolver.aaa(EMPTYUI8); | ||
}); | ||
}); | ||
}); | ||
}); | ||
await run(); | ||
|
||
await resolver.aaa(new Uint8Array([5, 3, 2, 1, 0])).then(console.log); | ||
|
||
termminate(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,189 @@ | ||
import { getCallerFile } from "./helpers.ts"; | ||
import { genTaskID } from "./helpers.ts"; | ||
import { createContext } from "./main.ts"; | ||
import type { PromiseMap } from "./mainQueue.ts"; | ||
|
||
type Args = "void" | "uint8"; | ||
const symbol = Symbol.for("FIXEDPOINT"); | ||
|
||
type FixPoint<A extends Args> = { | ||
args: A; | ||
f: ( | ||
args: A extends "void" ? void : Uint8Array, | ||
) => Promise<Uint8Array>; | ||
}; | ||
|
||
type SecondPart = { | ||
statusSignal: 224 | 192; | ||
[symbol]: string; | ||
id: number; | ||
importedFrom: string; | ||
}; | ||
|
||
type Composed = { | ||
args: Args; | ||
f: Function; | ||
} & SecondPart; | ||
|
||
type ReturnFixed<A extends Args> = FixPoint<A> & SecondPart; | ||
|
||
export const fixedPoint = <A extends Args>( | ||
I: FixPoint<A>, | ||
): ReturnFixed<A> => { | ||
return ({ | ||
...I, | ||
statusSignal: I.args === "void" ? 224 : 192, | ||
id: genTaskID(), | ||
importedFrom: new URL(getCallerFile(2)).href, | ||
[symbol]: "vixeny", | ||
}); | ||
}; | ||
|
||
type UnionReturnFixed = ReturnFixed<Args>; | ||
|
||
type FunctionMapType<T extends Record<string, Composed>> = { | ||
[K in keyof T]: T[K]["f"]; | ||
}; | ||
|
||
export type GetFunctions = ReturnType<typeof getFunctions>; | ||
|
||
export const getFunctions = async ({ list, ids }: { | ||
list: string[]; | ||
isWorker: boolean; | ||
ids: number[]; | ||
}) => { | ||
const results = await Promise.all( | ||
list.map(async (imports) => { | ||
const module = await import(imports); | ||
return Object.entries(module) // Use `Object.entries` to include names | ||
.filter( | ||
([_, value]): value is ReturnFixed<any> => | ||
typeof value === "object" && | ||
value !== null && | ||
!Array.isArray(value) && | ||
Object.getOwnPropertySymbols(value).some( | ||
(sym) => sym === Symbol.for("FIXEDPOINT"), | ||
), | ||
) | ||
.map(([name, value]) => ({ | ||
//@ts-ignore trust me | ||
...value, | ||
name, | ||
})); | ||
}), | ||
); | ||
|
||
// Flatten the results, filter by IDs, and sort | ||
const flattenedResults = results | ||
.flat() | ||
.filter((obj) => ids.includes(obj.id)) | ||
.sort((a, b) => a.name.localeCompare(b.name)); | ||
|
||
return flattenedResults as unknown as (UnionReturnFixed & { name: string })[]; | ||
}; | ||
|
||
const toListAndIds = (args: Record<string, Composed>, filter?: string) => { | ||
const result = Object.values(args) | ||
.reduce( | ||
(acc, v) => ( | ||
acc[0].add(v.importedFrom), acc[1].add(v.id), acc | ||
), | ||
[ | ||
new Set<string>(), | ||
new Set<number>(), | ||
] as [ | ||
Set<string>, | ||
Set<number>, | ||
], | ||
); | ||
|
||
if (filter) { | ||
console.log(filter); | ||
result[0].delete(filter); | ||
console.log(result); | ||
} | ||
|
||
return Object.fromEntries([ | ||
["list", [...result[0]]], | ||
["ids", [...result[1]]], | ||
]) as { | ||
list: string[]; | ||
ids: number[]; | ||
}; | ||
}; | ||
|
||
const loopingBetweenThreads = | ||
((n) => (functions: Function[]) => (max: number) => (args: any) => | ||
n === max ? functions[n = 0](args) : functions[n++](args))(0); | ||
|
||
export const compose = ({ | ||
threads, | ||
}: { | ||
threads?: number; | ||
}) => | ||
<T extends Record<string, Composed>>(args: T) => { | ||
const promisesMap: PromiseMap = new Map(); | ||
|
||
const { list, ids } = toListAndIds(args); | ||
|
||
const listOfFunctions = Object.entries(args).map(([k, v]) => ({ | ||
...v, | ||
name: k, | ||
})) | ||
.sort((a, b) => a.name.localeCompare(b.name)); | ||
|
||
const workers = Array.from({ | ||
length: threads ?? 1, | ||
}) | ||
.map((_) => | ||
createContext({ | ||
promisesMap, | ||
list, | ||
ids, | ||
}) | ||
); | ||
|
||
const map = workers.map( | ||
(worker) => { | ||
return listOfFunctions | ||
.map((list, index) => ({ ...list, index })) | ||
.reduce((acc, v) => { | ||
{ | ||
acc.set( | ||
v.name, | ||
worker.resolver({ | ||
queue: worker.queue, | ||
fnNumber: v.index, | ||
statusSignal: v.statusSignal, | ||
}), | ||
); | ||
} | ||
return acc; | ||
}, new Map<string, ReturnType<typeof worker.resolver>>()); | ||
}, | ||
) | ||
.reduce((acc, map) => { | ||
map.forEach( | ||
(v, k) => { | ||
const fun = acc.get(k); | ||
if (fun) { | ||
acc.set(k, [...fun, v]); | ||
} else { | ||
acc.set(k, [v]); | ||
} | ||
}, | ||
); | ||
|
||
return acc; | ||
}, new Map<string, Function[]>()); | ||
|
||
const resolve = new Map<string, (args: any) => Promise<any>>(); | ||
map.forEach((v, k) => { | ||
resolve.set(k, loopingBetweenThreads(v)(v.length)); | ||
}); | ||
|
||
return { | ||
termminate: () => workers.forEach((worker) => worker.kills()), | ||
resolver: Object.fromEntries(resolve) as unknown as FunctionMapType<T>, | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { fixedPoint } from "./fixpoint.ts"; | ||
|
||
export const aaa = fixedPoint({ | ||
args: "uint8", | ||
f: async (arr) => { | ||
// Simulate an expensive operation | ||
|
||
let time = 100000; | ||
|
||
while (time !== 0) { | ||
performance.now(); | ||
time--; | ||
} | ||
|
||
return Array.from(arr).map((num) => num * 2); | ||
}, | ||
}); | ||
|
||
export const bbb = fixedPoint({ | ||
args: "uint8", | ||
f: async (arr) => new Uint8Array([2]), | ||
}); | ||
|
||
export const ccc = fixedPoint({ | ||
args: "uint8", | ||
f: async (arr) => new Uint8Array([3]), | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.