henrygd/semaphore hiện có 47 sao trên GitHub, viết chủ yếu bằng TypeScript. Faster inline semaphores and mutexes in javascript
Tóm tắt dựng từ metadata GitHub của chính dự án — chưa có bài review TopGit. Trang sẽ tự động cập nhật khi bài review đầy đủ được xuất bản.
VÌ SAO CHƯA CÓ REVIEW
TopGit viết bài đầy đủ cho repo có nhiều sao nhất và được yêu cầu nhiều nhất. Trang này là snapshot trong thời gian chờ — xem README gốc ở tab READ ME.
Fast inline semaphores and mutexes. See comparisons and benchmarks.
Semaphores limit simultaneous access to code and resources (e.g. a file) among multiple concurrent tasks.
Works with:
Usage
Create or retrieve a semaphore by calling getSemaphore with optional key and concurrency limit.
const sem = getSemaphore('key', 1)
Use the acquire and release methods to limit access.
await sem.acquire()
// access here is limited to one task at a time
sem.release()
Full example
We use semaphores here to prevent multiple requests to an API for the same resource.
The first calls to fetchPokemon will acquire access to the protected code. Subsequent calls will wait, then return the data from the cache.
We use a key to allow access based on the name. This lets ditto and snorlax run simultaneously.
import { getSemaphore } from '@henrygd/semaphore'
const cache = new Map()
for (let i = 0; i < 5; i++) {
fetchPokemon('ditto')
fetchPokemon('snorlax')
}
async function fetchPokemon(name) {
// get semaphore with key based on name
const sem = getSemaphore(name)
// acquire access from the semaphore
await sem.acquire()
try {
// return data from cache if available
if (cache.has(name)) {
console.log('Cache hit:', name)
return cache.get(name)
}
// otherwise fetch from API
console.warn('Fetching from API:', name)
const res = await fetch(`https://pokeapi.co/api/v2/pokemon/${name}`)
const json = await res.json()
cache.set(name, json)
return json
} finally {
// release access when done
sem.release()
}
}
Interface
/**
* Creates or retrieves existing semaphore with optional key and concurrency level.
*
* key - Key used to identify the semaphore. Defaults to `Symbol()`.
* concurrency - Maximum concurrent tasks allowed access. Defaults to `1`.
*/
function getSemaphore(key?: any, concurrency?: number): Semaphore
interface Semaphore {
/** Returns a promise that resolves when access is acquired */
acquire(): Promise<void>
/** Release access to the semaphore */
release(): void
/** Returns the total number of tasks active or waiting for access */
size(): number
}
Keys and persistence
Keyed semaphores are held in a Map and deleted from the Map once they've been acquired and fully released (no waiting tasks).
If you need to reuse the same semaphore even after deletion from the Map, use a persistent variable instead of calling getSemaphore again.
Concurrency
Concurrency is set for each semaphore on first creation via getSemaphore. If called again using the key for an active semaphore, the concurrency argument is ignored and the existing semaphore is returned.
Comparisons and benchmarks
Note that we're looking at libraries which provide a promise-based locking mechanism, not callbacks.
Library
Version
Bundle size (B)
Keys
Weekly Downloads
@henrygd/semaphore
0.0.1
267
yes
¯\_(ツ)_/¯
async-mutex
0.5.0
4,758
no
1,639,071
async-sema
3.1.1
3,532
no
1,258,877
await-semaphore
0.1.3
1,184
no
60,449
@shopify/semaphore
3.1.0
604
no
29,089
If there's a library you'd like added to the table or benchmarks, please open an issue.
Benchmarks
All libraries run the same test. Each operation measures how long it takes a binary semaphore with 1,000 queued acquire requests to allow and release all requests.
Browser benchmark
This test was run in Chromium. Chrome and Edge are the same. Safari is more lopsided with Vercel's async-sema dropping to third. Firefox, though I love and respect it, seems to be hard capped by slow promise handling, with async-mutex not far behind.
You can run or tweak for yourself here: https://jsbm.dev/8bBxR1pBLw0TM
Note: await-semaphore is extremely slow for some reason and I didn't want to include it in the image because it seems excessive. Not sure what's happening there.
Node.js benchmark
Bun benchmark
Deno benchmark
Cloudflare Workers benchmark
Uses oha to make 1,000 requests to each worker. Each request creates a semaphore and resolves 5,000 acquisitions / releases.
This was run locally using Wrangler. Wrangler uses the same workerd runtime as workers deployed to Cloudflare, so the relative difference should be accurate. Here's the repo for this benchmark.
Library
Requests/sec
Total (sec)
Average
Slowest
@henrygd/semaphore
941.8135
1.0618
0.0521
0.0788
async-mutex
569.5130
1.7559
0.0862
0.1251
async-sema
375.7332
2.6615
0.1308
0.1818
@shopify/semaphore
167.8239
5.9586
0.2925
0.4063
await-semaphore*
n/a
n/a
n/a
n/a
* await-semaphore does not work with concurrent requests.
Related
@henrygd/queue - Tiny async queue with concurrency control. Like p-limit or fastq, but smaller and faster.
Trang TopGit này là một snapshot — tab "Readme" hiển thị nguyên văn README của repo (đã bỏ link, giữ ảnh). Repo GitHub ở github.com/henrygd/semaphore là nguồn chính thức.
henrygd/semaphore có phải mã nguồn mở không?
Có — henrygd/semaphore phát hành theo license MIT, nghĩa là mã nguồn mở để đọc, fork và (tùy license) tái sử dụng. Mã: github.com/henrygd/semaphore.
henrygd/semaphore có website riêng không?
TopGit chưa ghi nhận URL trang chủ cho henrygd/semaphore. Phần README ở tab phía trên thường có link demo, hoặc xem mô tả GitHub của repo.
henrygd/semaphore dùng license gì?
henrygd/semaphore phát hành theo license MIT. Nên mở file LICENSE trên GitHub để xác nhận — license metadata đôi khi lệch với thực tế dự án.
henrygd/semaphore là gì?
henrygd/semaphore (henrygd/semaphore) là dự án TypeScript trên GitHub. Theo mô tả gốc: Faster inline semaphores and mutexes in javascript
Đọc đầy đủ README ở tab phía trên.
Muốn nghe thêm một ý kiến về semaphore?
Hỏi một AI đọc được trang này — một cú bấm là có ngay nhận định về semaphore.