ciorent 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/deferred.d.ts +22 -0
- package/deferred.js +1 -0
- package/index.d.ts +46 -0
- package/index.js +1 -0
- package/iterators.d.ts +33 -0
- package/iterators.js +1 -0
- package/mutex.d.ts +17 -0
- package/mutex.js +1 -0
- package/package.json +1 -38
- package/rate-limit.d.ts +22 -0
- package/rate-limit.js +1 -0
- package/semaphore.d.ts +46 -0
- package/semaphore.js +1 -0
- package/signal.d.ts +41 -0
- package/signal.js +1 -0
- package/utils.d.ts +5 -0
- package/utils.js +1 -0
- package/bench/await.bench.ts +0 -29
- package/bench/bun.lock +0 -38
- package/bench/package.json +0 -11
- package/bench/promise-all.bench.ts +0 -42
- package/bench/semaphore.bench.ts +0 -101
- package/bench/shallow-clone.bench.ts +0 -69
- package/bench/tsconfig.json +0 -3
- package/biome.json +0 -62
- package/bun.lock +0 -117
- package/scripts/bench.ts +0 -38
- package/scripts/build.ts +0 -62
- package/scripts/publish.ts +0 -4
- package/scripts/report-size.ts +0 -33
- package/scripts/task.ts +0 -8
- package/scripts/tsconfig.json +0 -12
- package/scripts/tsconfig.ts +0 -16
- package/scripts/utils.ts +0 -15
- package/src/index.ts +0 -96
- package/src/mutex.ts +0 -44
- package/src/rate-limit.ts +0 -64
- package/src/semaphore.ts +0 -74
- package/src/signal.ts +0 -71
- package/src/utils.ts +0 -16
- package/tsconfig.json +0 -42
package/deferred.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface Deferred<T> {
|
|
2
|
+
get: Promise<T>;
|
|
3
|
+
set: T extends undefined ? (value?: T) => void : (value: T) => void;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Create a deferred value.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const result = deferred.init();
|
|
10
|
+
*
|
|
11
|
+
* // Set result value, unblock all
|
|
12
|
+
* // coroutines waiting for the results
|
|
13
|
+
* result.set(10);
|
|
14
|
+
*
|
|
15
|
+
* // Get result value
|
|
16
|
+
* await result.get;
|
|
17
|
+
*/
|
|
18
|
+
export declare const init: <T>() => Deferred<T>;
|
|
19
|
+
/**
|
|
20
|
+
* Reset a deferred value.
|
|
21
|
+
*/
|
|
22
|
+
export declare const reset: (value: Deferred<any>) => void;
|
package/deferred.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{loadedResolve,loadResolve}from"./utils.js";export let init=()=>({get:new Promise(loadResolve),set:loadedResolve});export let reset=value=>{value.get=new Promise(loadResolve);value.set=loadedResolve};
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Continue the execution on next event loop cycle.
|
|
3
|
+
*
|
|
4
|
+
* You can `await` this **occasionally** in an expensive synchronous operation to avoid
|
|
5
|
+
* blocking the main thread and let other asynchronous task to run.
|
|
6
|
+
*/
|
|
7
|
+
export declare const nextTick: Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Get the state of a promise on next tick:
|
|
10
|
+
* - `0`: Input promise rejected
|
|
11
|
+
* - `1`: Input promise resolves
|
|
12
|
+
* - `2`: Input promise pending
|
|
13
|
+
*/
|
|
14
|
+
export declare const state: (p: Promise<any>) => Promise<0 | 1 | 2>;
|
|
15
|
+
/**
|
|
16
|
+
* Check whether a value is awaitable.
|
|
17
|
+
* @param p
|
|
18
|
+
* @returns
|
|
19
|
+
*/
|
|
20
|
+
export declare const isThenable: <T>(p: unknown) => p is PromiseLike<T>;
|
|
21
|
+
/**
|
|
22
|
+
* Timeout a promise.
|
|
23
|
+
* @param p
|
|
24
|
+
* @param ms
|
|
25
|
+
*/
|
|
26
|
+
export declare const timeout: <T>(p: Promise<T>, ms: number) => Promise<T | void>;
|
|
27
|
+
/**
|
|
28
|
+
* Sleep for a duration.
|
|
29
|
+
* @param ms - Sleep duration in milliseconds
|
|
30
|
+
*/
|
|
31
|
+
export declare const sleep: (ms: number) => Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Sleep for a duration synchronously.
|
|
34
|
+
*
|
|
35
|
+
* This method blocks the current thread.
|
|
36
|
+
*
|
|
37
|
+
* On the browser it only works in workers.
|
|
38
|
+
* @param ms - Sleep duration in milliseconds
|
|
39
|
+
*/
|
|
40
|
+
export declare const sleepSync: (ms: number) => void;
|
|
41
|
+
export * as deferred from "./deferred.js";
|
|
42
|
+
export * as mutex from "./mutex.js";
|
|
43
|
+
export * as limit from "./rate-limit.js";
|
|
44
|
+
export * as semaphore from "./semaphore.js";
|
|
45
|
+
export * as signal from "./signal.js";
|
|
46
|
+
export * as iters from "./iterators.js";
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{loadedReject,loadedResolve,loadResolve,loadResolvers}from"./utils.js";export let nextTick=Promise.resolve();let getFinishedState=async(s,p)=>{try{await p;s[0]=1}catch(e){s[0]=0;return p}};export let state=async p=>{let res=[2];getFinishedState(res,p);await nextTick;return res[0]};export let isThenable=p=>p!==null&&typeof p===`object`&&!Array.isArray(p)&&typeof p.then===`function`;export let timeout=(p,ms)=>{let promise=new Promise(loadResolvers);setTimeout(loadedResolve,ms);p.then(loadedResolve,loadedReject);return promise};export let sleep=globalThis.Bun?.sleep??globalThis.process?.getBuiltinModule?.(`timers/promises`).setTimeout??(ms=>{let promise=new Promise(loadResolve);setTimeout(loadedResolve,ms);return promise});let sharedBuf=new Int32Array(new SharedArrayBuffer(4));export let sleepSync=globalThis.Bun?.sleepSync??(ms=>{Atomics.wait(sharedBuf,0,0,ms)});export*as deferred from"./deferred.js";export*as mutex from"./mutex.js";export*as limit from"./rate-limit.js";export*as semaphore from"./semaphore.js";export*as signal from"./signal.js";export*as iters from"./iterators.js";
|
package/iterators.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Describe an async iterator created by `race()`
|
|
3
|
+
*/
|
|
4
|
+
export interface RaceIterator<T> extends AsyncIterator<T> {
|
|
5
|
+
_: Promise<T>[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Race promises and return them in order
|
|
9
|
+
*/
|
|
10
|
+
export declare const race: <T>(promises: Promise<T>[]) => RaceIterator<T>;
|
|
11
|
+
/**
|
|
12
|
+
* Describe an async iterator created by `map()`
|
|
13
|
+
*/
|
|
14
|
+
export interface MapIterator<
|
|
15
|
+
I,
|
|
16
|
+
O
|
|
17
|
+
> extends AsyncIterator<O> {
|
|
18
|
+
_: AsyncIterator<I>;
|
|
19
|
+
f: (value: I) => Promise<Awaited<O>>;
|
|
20
|
+
}
|
|
21
|
+
export declare const map: <
|
|
22
|
+
I,
|
|
23
|
+
O
|
|
24
|
+
>(iterator: AsyncIterator<I>, mapFn: MapIterator<I, O>["f"]) => MapIterator<I, O>;
|
|
25
|
+
/**
|
|
26
|
+
* Describe an async iterator created by `filter()`
|
|
27
|
+
*/
|
|
28
|
+
export interface FilterIterator<T> extends AsyncIterator<T> {
|
|
29
|
+
_: AsyncIterator<T>;
|
|
30
|
+
f: (value: T) => Promise<boolean> | boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare const filter: <T>(iterator: AsyncIterator<T>, filterFn: FilterIterator<T>["f"]) => FilterIterator<T>;
|
|
33
|
+
export declare const find: <T>(iterator: AsyncIterator<T>, findFn: (value: T) => Promise<boolean> | boolean) => Promise<T | undefined>;
|
package/iterators.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{loadedResolve,loadResolve}from"./utils.ts";let iteratorDoneResult={done:true,value:undefined};let promiseIteratorDoneResult=Promise.resolve(iteratorDoneResult);let toIteratorResult=value=>({done:false,value});let resolveNext=async(p,resolvers)=>{try{let res=await p;resolvers.pop()(res)}catch{resolvers.pop()(p)}};function raceNext(){return this._.pop()?.then(toIteratorResult)??promiseIteratorDoneResult}export let race=promises=>{let last=promises.length-1;let waitingPromises=new Array(last+1);for(let i=0,resolvers=new Array(last+1);i<=last;i++){waitingPromises[last-i]=new Promise(loadResolve);resolvers[last-i]=loadedResolve;resolveNext(promises[i],resolvers)}return{next:raceNext,_:waitingPromises}};async function mapNext(){let p=await this._.next();if(p.done)return iteratorDoneResult;let res=this.f(p.value);return toIteratorResult(res instanceof Promise?await res:res)}export let map=(iterator,mapFn)=>({next:mapNext,_:iterator,f:mapFn});async function filterNext(){let p=await this._.next();while(!p.done){let res=this.f(p.value);if(res instanceof Promise?await res:res)return p;p=await this._.next()}return iteratorDoneResult}export let filter=(iterator,filterFn)=>({next:filterNext,_:iterator,f:filterFn});export let find=async(iterator,findFn)=>{let p=await iterator.next();while(!p.done){let res=findFn(p.value);if(res instanceof Promise?await res:res)return p.value;p=await iterator.next()}};
|
package/mutex.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Extend } from "./utils.js";
|
|
2
|
+
/**
|
|
3
|
+
* Describe a mutex.
|
|
4
|
+
*/
|
|
5
|
+
export type Mutex = [Promise<void>];
|
|
6
|
+
/**
|
|
7
|
+
* Create a mutex.
|
|
8
|
+
*/
|
|
9
|
+
export declare const init: () => Mutex;
|
|
10
|
+
/**
|
|
11
|
+
* Acquire a mutex.
|
|
12
|
+
*/
|
|
13
|
+
export declare const acquire: (mu: Extend<Mutex>) => Promise<() => void>;
|
|
14
|
+
/**
|
|
15
|
+
* Automatically acquire and run a task.
|
|
16
|
+
*/
|
|
17
|
+
export declare const run: <const T extends (...args: any[]) => Promise<any>>(mu: Extend<Mutex>, fn: T, ...args: Parameters<T>) => ReturnType<T>;
|
package/mutex.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{nextTick}from"./index.js";import{loadedResolve,loadResolve}from"./utils.js";export let init=()=>[nextTick];export let acquire=async mu=>{let currentLock=mu[0];mu[0]=new Promise(loadResolve);let release=loadedResolve;await currentLock;return release};let chainLock=async(lock,fn,...args)=>{try{await lock}finally{return fn(...args)}};export let run=(mu,fn,...args)=>mu[0]=chainLock(mu[0],fn,...args);
|
package/package.json
CHANGED
|
@@ -1,38 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "ciorent",
|
|
3
|
-
"version": "1.0.5",
|
|
4
|
-
"description": "A lightweight, low-overhead concurrency library",
|
|
5
|
-
"homepage": "https://re-utils.pages.dev/concurrency",
|
|
6
|
-
"repository": {
|
|
7
|
-
"type": "git",
|
|
8
|
-
"url": "git+https://github.com/re-utils/ciorent.git"
|
|
9
|
-
},
|
|
10
|
-
"keywords": [
|
|
11
|
-
"low-overhead",
|
|
12
|
-
"lightweight",
|
|
13
|
-
"concurrency",
|
|
14
|
-
"cross-runtime"
|
|
15
|
-
],
|
|
16
|
-
"license": "MIT",
|
|
17
|
-
"type": "module",
|
|
18
|
-
"scripts": {
|
|
19
|
-
"task": "bun scripts/task.ts",
|
|
20
|
-
"fmt": "biome format .",
|
|
21
|
-
"lint": "biome check",
|
|
22
|
-
"build:test": "bun task build && bun test",
|
|
23
|
-
"build:publish": "bun task build && bun task report-size && bun task publish"
|
|
24
|
-
},
|
|
25
|
-
"devDependencies": {
|
|
26
|
-
"@biomejs/biome": "^2.1.3",
|
|
27
|
-
"@types/bun": "^1.2.19",
|
|
28
|
-
"mitata": "^1.0.34",
|
|
29
|
-
"oxc-minify": "^0.64.0",
|
|
30
|
-
"oxc-transform": "^0.65.0",
|
|
31
|
-
"typescript": "^5.9.2",
|
|
32
|
-
"jiti": "^2.5.1",
|
|
33
|
-
"ciorent": "./lib"
|
|
34
|
-
},
|
|
35
|
-
"trustedDependencies": [
|
|
36
|
-
"@biomejs/biome"
|
|
37
|
-
]
|
|
38
|
-
}
|
|
1
|
+
{"name":"ciorent","version":"1.0.7","description":"A lightweight, low-overhead concurrency library","homepage":"https://re-utils.pages.dev/concurrency","repository":{"type":"git","url":"git+https://github.com/re-utils/ciorent.git"},"keywords":["low-overhead","lightweight","concurrency","cross-runtime"],"license":"MIT","type":"module","exports":{"./iterators":"./iterators.js",".":"./index.js","./utils":"./utils.js","./semaphore":"./semaphore.js","./rate-limit":"./rate-limit.js","./deferred":"./deferred.js","./mutex":"./mutex.js","./signal":"./signal.js"}}
|
package/rate-limit.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Describe a rate limiter.
|
|
3
|
+
*/
|
|
4
|
+
export type Limiter = (limit: number, ms: number) => () => boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Fixed window strategy.
|
|
7
|
+
* @param limit
|
|
8
|
+
* @param ms
|
|
9
|
+
*/
|
|
10
|
+
export declare const fixedWindow: Limiter;
|
|
11
|
+
/**
|
|
12
|
+
* Sliding window strategy.
|
|
13
|
+
* @param limit
|
|
14
|
+
* @param ms
|
|
15
|
+
*/
|
|
16
|
+
export declare const slidingWindow: Limiter;
|
|
17
|
+
/**
|
|
18
|
+
* Token bucket strategy.
|
|
19
|
+
* @param limit
|
|
20
|
+
* @param ms
|
|
21
|
+
*/
|
|
22
|
+
export declare const tokenBucket: Limiter;
|
package/rate-limit.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export let fixedWindow=(limit,ms)=>{let cur=limit;let unlock=()=>{cur=limit};return()=>{if(cur===0)return false;if(cur--===limit)setTimeout(unlock,ms);return true}};export let slidingWindow=(limit,ms)=>{let cur=limit;let unlock=()=>{cur++};return()=>{if(cur===0)return false;cur--;setTimeout(unlock,ms);return true}};export let tokenBucket=(limit,ms)=>{let cur=limit;ms/=limit;let unlock=()=>{if(cur++<limit)setTimeout(unlock,ms)};return()=>{if(cur===0)return false;if(cur--===limit)setTimeout(unlock,ms);return true}};
|
package/semaphore.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type Extend } from "./utils.js";
|
|
2
|
+
type QueueItem = () => void;
|
|
3
|
+
type Queue = [(QueueItem | null)[], len: number, head: number, tail: number];
|
|
4
|
+
export type Semaphore = [...Queue, remain: number];
|
|
5
|
+
/**
|
|
6
|
+
* Check whether the semaphore queue is full.
|
|
7
|
+
*/
|
|
8
|
+
export declare const full: (qu: Extend<Semaphore>) => boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Create a semaphore.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* // maximum of 10 concurrent tasks and 200 waiting tasks.
|
|
14
|
+
* const sem = semaphore.init(10, 200);
|
|
15
|
+
*/
|
|
16
|
+
export declare const init: (permits: number, capacity: number) => Semaphore;
|
|
17
|
+
/**
|
|
18
|
+
* Acquire a permit.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
*
|
|
22
|
+
* if (semaphore.full(sem)) {
|
|
23
|
+
* // Internal queue is full
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* await semaphore.acquire(sem);
|
|
27
|
+
*
|
|
28
|
+
* // Do something and then release the permit.
|
|
29
|
+
* semaphore.release(sem);
|
|
30
|
+
*/
|
|
31
|
+
export declare const acquire: (sem: Extend<Semaphore>) => Promise<void> | void;
|
|
32
|
+
/**
|
|
33
|
+
* Release a permit.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* semaphore.release(sem);
|
|
37
|
+
*/
|
|
38
|
+
export declare const release: (sem: Extend<Semaphore>) => void;
|
|
39
|
+
/**
|
|
40
|
+
* @param task Task to limit
|
|
41
|
+
* @param sem Target semaphore
|
|
42
|
+
* @throws {Error} when `sem` internal queue is full
|
|
43
|
+
* @returns The limited function
|
|
44
|
+
*/
|
|
45
|
+
export declare const limit: <Fn extends (...args: any[]) => Promise<any>>(task: Fn, sem: Extend<Semaphore>) => Fn;
|
|
46
|
+
export {};
|
package/semaphore.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{loadedResolve,loadResolve}from"./utils.js";let push=(qu,item)=>{let tail=qu[3];qu[3]=tail+1===qu[1]?0:tail+1;qu[0][tail]=item};let pop=qu=>{let head=qu[2];qu[2]=head+1===qu[1]?0:head+1;let val=qu[0][head];qu[0][head]=null;return val};export let full=qu=>qu[0].length+qu[4]<=0;export let init=(permits,capacity)=>[new Array(capacity).fill(null),capacity,0,0,permits];export let acquire=sem=>{if(--sem[4]<0){let promise=new Promise(loadResolve);push(sem,loadedResolve);return promise}};export let release=sem=>{sem[4]++<0&&pop(sem)()};export let limit=(task,sem)=>async(...args)=>{if(full(sem))throw new Error(`Semaphore internal queue is full`);if(--sem[4]<0){let promise=new Promise(loadResolve);push(sem,loadedResolve);await promise}try{return await task(...args)}finally{release(sem)}};
|
package/signal.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Describe a signal.
|
|
3
|
+
*/
|
|
4
|
+
export type Signal = [interrupted: boolean, ...parents: Signal[]];
|
|
5
|
+
/**
|
|
6
|
+
* Create a signal.
|
|
7
|
+
*/
|
|
8
|
+
export declare const init: () => Signal;
|
|
9
|
+
/**
|
|
10
|
+
* Create a signal that aborts when any of the input signals abort.
|
|
11
|
+
* @param sigs
|
|
12
|
+
*/
|
|
13
|
+
export declare const any: (signals: Signal[]) => Signal;
|
|
14
|
+
/**
|
|
15
|
+
* Create a signal that when interrupted will interrupt a group of other signals.
|
|
16
|
+
*/
|
|
17
|
+
export declare const group: (signals: Signal[]) => Signal;
|
|
18
|
+
/**
|
|
19
|
+
* Check whether the signal has been aborted.
|
|
20
|
+
* @param t
|
|
21
|
+
*/
|
|
22
|
+
export declare const aborted: (t: Signal) => boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Abort a signal.
|
|
25
|
+
* @param t
|
|
26
|
+
*/
|
|
27
|
+
export declare const abort: (t: Signal) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Abort a signal after a duration.
|
|
30
|
+
* @param t
|
|
31
|
+
*/
|
|
32
|
+
export declare const abortAfter: (ms: number, t: Signal) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Create a signal that aborts after ms.
|
|
35
|
+
* @param ms
|
|
36
|
+
*/
|
|
37
|
+
export declare const timeout: (ms: number) => Signal;
|
|
38
|
+
/**
|
|
39
|
+
* Attach a signal to a `DisposableStack` or `AsyncDisposableStack`
|
|
40
|
+
*/
|
|
41
|
+
export declare const adopt: (t: Signal, stack: DisposableStack | AsyncDisposableStack) => void;
|
package/signal.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export let init=()=>[false];export let any=signals=>{let sig=[false];for(let i=0;i<signals.length;i++)signals[i].push(sig);return sig};let _=[false];export let group=signals=>_.concat(signals);export let aborted=t=>t[0];export let abort=t=>{if(!t[0]){t[0]=true;if(t.length>1)for(let i=1;i<t.length;i++)abort(t[i])}};export let abortAfter=(ms,t)=>{setTimeout(()=>abort(t),ms)};export let timeout=ms=>{let sig=[false];abortAfter(ms,sig);return sig};export let adopt=(t,stack)=>{stack.adopt(t,abort)};
|
package/utils.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type Extend<T extends any[]> = [...T, ...any[]];
|
|
2
|
+
export declare let loadedResolve: (res?: any) => void;
|
|
3
|
+
export declare let loadedReject: (reason?: any) => void;
|
|
4
|
+
export declare const loadResolvers: (res: (value?: any) => void, rej: (reason?: any) => void) => void;
|
|
5
|
+
export declare const loadResolve: (res: (value?: any) => void) => void;
|
package/utils.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export let loadedResolve;export let loadedReject;export let loadResolvers=(res,rej)=>{loadedResolve=res;loadedReject=rej};export let loadResolve=res=>{loadedResolve=res};
|
package/bench/await.bench.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { bench, do_not_optimize, run, summary } from 'mitata';
|
|
2
|
-
|
|
3
|
-
// Example benchmark
|
|
4
|
-
summary(() => {
|
|
5
|
-
bench('Await', function* () {
|
|
6
|
-
yield {
|
|
7
|
-
[0]() {
|
|
8
|
-
return Promise.resolve(1);
|
|
9
|
-
},
|
|
10
|
-
async bench(data: any) {
|
|
11
|
-
do_not_optimize(await data);
|
|
12
|
-
},
|
|
13
|
-
};
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
bench('Await non-promise', function* () {
|
|
17
|
-
yield {
|
|
18
|
-
[0]() {
|
|
19
|
-
return 1;
|
|
20
|
-
},
|
|
21
|
-
async bench(data: any) {
|
|
22
|
-
do_not_optimize(await data);
|
|
23
|
-
},
|
|
24
|
-
};
|
|
25
|
-
});
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
// Start the benchmark
|
|
29
|
-
run();
|
package/bench/bun.lock
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"lockfileVersion": 1,
|
|
3
|
-
"configVersion": 0,
|
|
4
|
-
"workspaces": {
|
|
5
|
-
"": {
|
|
6
|
-
"dependencies": {
|
|
7
|
-
"@types/mutexify": "^1.2.4",
|
|
8
|
-
"async-mutex": "^0.5.0",
|
|
9
|
-
"async-sema": "^3.1.1",
|
|
10
|
-
"bottleneck": "^2.19.5",
|
|
11
|
-
"limit-concur": "^4.0.0",
|
|
12
|
-
"mutexify": "^1.4.0",
|
|
13
|
-
"p-limit": "^6.2.0",
|
|
14
|
-
},
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
"packages": {
|
|
18
|
-
"@types/mutexify": ["@types/mutexify@1.2.4", "", {}, "sha512-mKNLg7IdppIDCNXiC1hNkNhdEdYnd5ErNnoNgEOERwU3DwD/S1/TBseob0Uq/QXWADBz7OWaWUoHa6IEUtrOEQ=="],
|
|
19
|
-
|
|
20
|
-
"async-mutex": ["async-mutex@0.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA=="],
|
|
21
|
-
|
|
22
|
-
"async-sema": ["async-sema@3.1.1", "", {}, "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg=="],
|
|
23
|
-
|
|
24
|
-
"bottleneck": ["bottleneck@2.19.5", "", {}, "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="],
|
|
25
|
-
|
|
26
|
-
"limit-concur": ["limit-concur@4.0.0", "", {}, "sha512-BXUCP52gLz8JA8/cRKkXswOV6FnA2gl8hL8DbgQuo8XA9NKcwU3Oq/Cg1JyAZ+gyNmFEZXI+ZYLes0BrZkl+7g=="],
|
|
27
|
-
|
|
28
|
-
"mutexify": ["mutexify@1.4.0", "", { "dependencies": { "queue-tick": "^1.0.0" } }, "sha512-pbYSsOrSB/AKN5h/WzzLRMFgZhClWccf2XIB4RSMC8JbquiB0e0/SH5AIfdQMdyHmYtv4seU7yV/TvAwPLJ1Yg=="],
|
|
29
|
-
|
|
30
|
-
"p-limit": ["p-limit@6.2.0", "", { "dependencies": { "yocto-queue": "^1.1.1" } }, "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA=="],
|
|
31
|
-
|
|
32
|
-
"queue-tick": ["queue-tick@1.0.1", "", {}, "sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag=="],
|
|
33
|
-
|
|
34
|
-
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
|
35
|
-
|
|
36
|
-
"yocto-queue": ["yocto-queue@1.2.1", "", {}, "sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg=="],
|
|
37
|
-
}
|
|
38
|
-
}
|
package/bench/package.json
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { bench, do_not_optimize, run, summary } from 'mitata';
|
|
2
|
-
|
|
3
|
-
// Example benchmark
|
|
4
|
-
summary(() => {
|
|
5
|
-
bench('Fill with null', function* () {
|
|
6
|
-
const DAT = new Array(6).fill(null);
|
|
7
|
-
|
|
8
|
-
yield {
|
|
9
|
-
[0]() {
|
|
10
|
-
return [...DAT];
|
|
11
|
-
},
|
|
12
|
-
[1]() {
|
|
13
|
-
return Promise.resolve(15);
|
|
14
|
-
},
|
|
15
|
-
async bench(data: any[], p: any) {
|
|
16
|
-
data[0] = p;
|
|
17
|
-
do_not_optimize(await Promise.all(data));
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
bench('Fill with resolved promises', function* () {
|
|
23
|
-
const resolvedPromise = Promise.resolve();
|
|
24
|
-
const DAT = new Array(6).fill(resolvedPromise);
|
|
25
|
-
|
|
26
|
-
yield {
|
|
27
|
-
[0]() {
|
|
28
|
-
return [...DAT];
|
|
29
|
-
},
|
|
30
|
-
[1]() {
|
|
31
|
-
return Promise.resolve(15);
|
|
32
|
-
},
|
|
33
|
-
async bench(data: any[], p: any) {
|
|
34
|
-
data[0] = p;
|
|
35
|
-
do_not_optimize(await Promise.all(data));
|
|
36
|
-
},
|
|
37
|
-
};
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// Start the benchmark
|
|
42
|
-
run();
|
package/bench/semaphore.bench.ts
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { semaphore, mutex } from 'ciorent';
|
|
2
|
-
import limitConcur from 'limit-concur';
|
|
3
|
-
import { limitFunction } from 'p-limit';
|
|
4
|
-
import { Mutex, Semaphore } from 'async-mutex';
|
|
5
|
-
import mutexify from 'mutexify/promise.js';
|
|
6
|
-
import { Sema } from 'async-sema';
|
|
7
|
-
|
|
8
|
-
import { bench, do_not_optimize, run, summary } from 'mitata';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const task = async () => {
|
|
12
|
-
await 0;
|
|
13
|
-
do_not_optimize(Math.random());
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const setup = (label: string, limited: () => Promise<any>) => {
|
|
17
|
-
bench(label, Function('f', `return async () => { await Promise.all([${
|
|
18
|
-
'f(),'.repeat(200)
|
|
19
|
-
}]); }`)(limited)).gc('inner');
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const setupSemaphoreCases = (permit: number) => {
|
|
23
|
-
setup(`permit ${permit} - limit-concur`, limitConcur(permit, task));
|
|
24
|
-
setup(`permit ${permit} - p-limit`, limitFunction(task, { concurrency: permit }));
|
|
25
|
-
|
|
26
|
-
{
|
|
27
|
-
const sem = semaphore.init(permit, 200 - permit);
|
|
28
|
-
setup(`permit ${permit} - ciorent (semaphore)`, async () => {
|
|
29
|
-
await semaphore.acquire(sem);
|
|
30
|
-
try {
|
|
31
|
-
await task();
|
|
32
|
-
} finally {
|
|
33
|
-
semaphore.release(sem);
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
{
|
|
39
|
-
const sem = new Semaphore(permit);
|
|
40
|
-
setup(`permit ${permit} - async-mutex (semaphore)`, () => sem.runExclusive(task));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
const sem = new Sema(permit);
|
|
45
|
-
setup(`permit ${permit} - async-sema`, async () => {
|
|
46
|
-
await sem.acquire();
|
|
47
|
-
try {
|
|
48
|
-
return await task();
|
|
49
|
-
} finally {
|
|
50
|
-
sem.release();
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
{
|
|
56
|
-
const sem = new Sema(permit, {
|
|
57
|
-
capacity: 200 - permit
|
|
58
|
-
});
|
|
59
|
-
setup(`permit ${permit} - async-sema (pre-allocated)`, async () => {
|
|
60
|
-
await sem.acquire();
|
|
61
|
-
try {
|
|
62
|
-
return await task();
|
|
63
|
-
} finally {
|
|
64
|
-
sem.release();
|
|
65
|
-
}
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
summary(() => {
|
|
71
|
-
setupSemaphoreCases(1);
|
|
72
|
-
|
|
73
|
-
{
|
|
74
|
-
const mu = mutex.init();
|
|
75
|
-
setup('permit 1 - ciorent (mutex)', () => mutex.run(mu, task));
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
{
|
|
79
|
-
const mu = new Mutex();
|
|
80
|
-
setup('permit 1 - async-mutex (mutex)', () => mu.runExclusive(task));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
{
|
|
84
|
-
const acquire = mutexify();
|
|
85
|
-
setup('permit 1 - mutexify', async () => {
|
|
86
|
-
const release = await acquire();
|
|
87
|
-
try {
|
|
88
|
-
return await task();
|
|
89
|
-
} finally {
|
|
90
|
-
release();
|
|
91
|
-
}
|
|
92
|
-
})
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
for (let permit = 2; permit < 128; permit <<= 1)
|
|
97
|
-
summary(() => {
|
|
98
|
-
setupSemaphoreCases(permit);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
run();
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { bench, do_not_optimize, type k_state, run, summary } from 'mitata';
|
|
2
|
-
|
|
3
|
-
// Example benchmark
|
|
4
|
-
summary(() => {
|
|
5
|
-
bench('Clone 2 arrays - Concat', function* (state: k_state) {
|
|
6
|
-
const DAT = new Array(state.get('len')).fill(0).map(Math.random);
|
|
7
|
-
const DAT2 = new Array(state.get('len')).map(Math.random);
|
|
8
|
-
|
|
9
|
-
yield {
|
|
10
|
-
[0]() {
|
|
11
|
-
return DAT;
|
|
12
|
-
},
|
|
13
|
-
[1]() {
|
|
14
|
-
return DAT2;
|
|
15
|
-
},
|
|
16
|
-
bench(data: any[], data1: any[]) {
|
|
17
|
-
do_not_optimize(data.concat(data1));
|
|
18
|
-
},
|
|
19
|
-
};
|
|
20
|
-
}).range('len', 2 ** 3, 2 ** 12);
|
|
21
|
-
|
|
22
|
-
bench('Clone 2 arrays - Spread', function* (state: k_state) {
|
|
23
|
-
const DAT = new Array(state.get('len')).fill(0).map(Math.random);
|
|
24
|
-
const DAT2 = new Array(state.get('len')).map(Math.random);
|
|
25
|
-
|
|
26
|
-
yield {
|
|
27
|
-
[0]() {
|
|
28
|
-
return DAT;
|
|
29
|
-
},
|
|
30
|
-
[1]() {
|
|
31
|
-
return DAT2;
|
|
32
|
-
},
|
|
33
|
-
bench(data: any[], data1: any[]) {
|
|
34
|
-
do_not_optimize([...data, ...data1]);
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
}).range('len', 2 ** 3, 2 ** 12);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
summary(() => {
|
|
41
|
-
bench('Clone 1 array - Concat', function* (state: k_state) {
|
|
42
|
-
const DAT = new Array(state.get('len')).fill(0).map(Math.random);
|
|
43
|
-
|
|
44
|
-
yield {
|
|
45
|
-
[0]() {
|
|
46
|
-
return DAT;
|
|
47
|
-
},
|
|
48
|
-
bench(data: any[]) {
|
|
49
|
-
do_not_optimize(data.concat([]));
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
}).range('len', 2 ** 3, 2 ** 12);
|
|
53
|
-
|
|
54
|
-
bench('Clone 1 array - Spread', function* (state: k_state) {
|
|
55
|
-
const DAT = new Array(state.get('len')).fill(0).map(Math.random);
|
|
56
|
-
|
|
57
|
-
yield {
|
|
58
|
-
[0]() {
|
|
59
|
-
return DAT;
|
|
60
|
-
},
|
|
61
|
-
bench(data: any[]) {
|
|
62
|
-
do_not_optimize([...data]);
|
|
63
|
-
},
|
|
64
|
-
};
|
|
65
|
-
}).range('len', 2 ** 3, 2 ** 12);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// Start the benchmark
|
|
69
|
-
run();
|
package/bench/tsconfig.json
DELETED
package/biome.json
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://biomejs.dev/schemas/2.1.3/schema.json",
|
|
3
|
-
"vcs": {
|
|
4
|
-
"enabled": false
|
|
5
|
-
},
|
|
6
|
-
"files": {
|
|
7
|
-
"experimentalScannerIgnores": ["node_modules"],
|
|
8
|
-
"includes": [
|
|
9
|
-
"**/*.{js,ts,jsx,tsx,json,astro,svelte,vue}",
|
|
10
|
-
"!{lib,bench}/**/*"
|
|
11
|
-
]
|
|
12
|
-
},
|
|
13
|
-
"javascript": {
|
|
14
|
-
"formatter": {
|
|
15
|
-
"quoteStyle": "single",
|
|
16
|
-
"arrowParentheses": "always",
|
|
17
|
-
"semicolons": "always"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"formatter": {
|
|
21
|
-
"enabled": true,
|
|
22
|
-
"indentStyle": "space",
|
|
23
|
-
"indentWidth": 2,
|
|
24
|
-
"bracketSpacing": true
|
|
25
|
-
},
|
|
26
|
-
"linter": {
|
|
27
|
-
"enabled": true,
|
|
28
|
-
"rules": {
|
|
29
|
-
"style": {
|
|
30
|
-
"noEnum": "error",
|
|
31
|
-
"noCommonJs": "error",
|
|
32
|
-
"useConsistentArrayType": "error",
|
|
33
|
-
"noNamespace": "error",
|
|
34
|
-
"noImplicitBoolean": "warn",
|
|
35
|
-
"noUselessElse": "error",
|
|
36
|
-
"useCollapsedElseIf": "error",
|
|
37
|
-
"useConst": "error",
|
|
38
|
-
"useNodejsImportProtocol": "error",
|
|
39
|
-
"useImportType": "error",
|
|
40
|
-
"useExponentiationOperator": "info"
|
|
41
|
-
},
|
|
42
|
-
"complexity": {
|
|
43
|
-
"noForEach": "info",
|
|
44
|
-
"noUselessCatch": "info",
|
|
45
|
-
"useArrowFunction": "warn"
|
|
46
|
-
},
|
|
47
|
-
"nursery": {
|
|
48
|
-
"noShadow": "warn",
|
|
49
|
-
"noGlobalDirnameFilename": "error",
|
|
50
|
-
"useIndexOf": "warn",
|
|
51
|
-
"noImportCycles": "error"
|
|
52
|
-
},
|
|
53
|
-
"correctness": {
|
|
54
|
-
"useYield": "warn",
|
|
55
|
-
"noUnusedImports": "warn",
|
|
56
|
-
"useImportExtensions": "error",
|
|
57
|
-
"useIsNan": "warn"
|
|
58
|
-
},
|
|
59
|
-
"recommended": false
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|