Files
2nd/10_Wiki/Topic_Programming/Programming & Language/bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처.md
T
Antigravity Agent 9148c358d0 docs(10_Wiki): 위키 전체 재구성 — Topic_* 폴더를 4개 카테고리로 통합 + 대규모 중복 제거
Topic_Agent/Topic_Blog/Topics/Topics_Biz/Topics_Meeting/Topics_Rag의 마크다운 지식 문서를
Topic_General/Topic_Programming/Topic_Graphic/Topic_Business 4개 카테고리로 재분류.

- 중복 제거: frontmatter의 status:duplicate/merged + duplicate_of/redirect_to 필드로
  자기 자신을 중복으로 선언한 리다이렉트 stub 1032개 제거, 완전 동일 내용 파일 472개 제거,
  동일 파일명·다른 내용 충돌 시 더 큰(완전한) 버전만 유지(162개 제거) — 총 1639개 중복 제거.
- 분류: 폴더 단위로 명확한 항목(AI_and_ML/Coding/Architecture 등 → Programming,
  Comfyui/Visual_Effects → Graphic, Topics_Biz/Topics_Meeting/사업 등 → Business,
  Poetic_Blog_Writing/창의성/Game_Design 등 → General)은 폴더 우선순위로,
  나머지 혼재 폴더(Topic_Agent/Topic_Blog/Topics 루트/Thinking & Reasoning/Other/UI_UX_Assets)는
  title/tags 키워드 스코어링으로 파일 단위 분류(불명확한 경우 General로 폴백).
  원본 폴더명은 "From_*" 서브폴더로 보존해 추적 가능성 유지.
- 최종 배치: Programming 2784 / General 1608 / Graphic 285 / Business 249 = 4926개 문서.
- 에이전트 운영 상태(.astra/.agent/.obsidian/sessions/memory/_company/docs/lessons/_shared/src)는
  지식 콘텐츠가 아니므로 재분류 대상에서 제외하고 원위치 유지.
- Topics/Topic_email(상위 보호 폴더 Topic_email과 파일명 100% 중복) 삭제 — 보호 폴더 자체는 미변경.
- 완전히 비게 된 Topic_Agent/Topic_Blog/Topics_Biz/Topics_Rag 폴더 제거.
2026-07-05 00:33:48 +09:00

228 lines
7.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
id: wiki-2026-0508-bitecs와-sharedarraybuffer를-결합한-멀
title: bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [bitECS multithreaded, SAB ECS, ECS parallel, bitECS SharedArrayBuffer]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [ecs, bitecs, sharedarraybuffer, parallel, gamedev, browser]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: TypeScript
framework: bitECS + Web Worker
---
# bitECS와 SharedArrayBuffer를 결합한 멀티스레드 고성능 아키텍처
## 매 한 줄
> **"매 bitECS Component = TypedArray on SAB"**. bitECS의 매 SoA layout 은 매 SharedArrayBuffer 와 매 자연스럽게 결합 — 매 component data 가 매 worker 에서 매 zero-copy 공유. 매 system 분산 + 매 stripe partition 으로 매 100k+ entity 를 매 60fps 에서 매 simulate 가능.
## 매 핵심
### 매 bitECS 구조
- **Entity**: 32-bit integer ID.
- **Component**: 매 TypedArray (Float32Array, Int32Array 등) per field, 매 indexed by entity ID.
- **System**: query → process loop.
- 매 SoA (Struct of Arrays) → 매 cache-friendly + SIMD-friendly.
### 매 SAB 통합 핵심
- bitECS 의 매 component 매 backing TypedArray 의 매 buffer 를 매 SAB 로 교체.
- 매 worker 에서 매 동일 component 에 매 동시 접근 가능.
- 매 system 별로 매 worker 분배 — 또는 매 entity range 별 분배.
### 매 partition strategy
1. **System-level**: physics worker, AI worker, render worker 매 별도.
2. **Entity-level**: entity ID 매 mod N → worker N 개에 분산.
3. **Stripe-level**: contiguous range, cache-friendly.
4. **Hybrid**: 매 read-heavy system 매 모든 worker, write 매 owner worker 만.
### 매 응용
1. **Boid/flocking**: 100k boids 매 4 worker 에서 stripe.
2. **Particle system**: SAB Float32 의 매 position/velocity, 매 worker 별 batch.
3. **Pathfinding**: A* 매 worker pool, 매 result 매 SAB 에 적재.
4. **Voxel chunk update**: 매 chunk 별 worker, 매 mesh build 매 OffscreenCanvas worker.
## 💻 패턴
### Pattern 1: bitECS component → SAB-backed
```typescript
// main.ts
import { createWorld, defineComponent, Types } from "bitecs";
const MAX_ENTITIES = 100_000;
const sab = new SharedArrayBuffer(MAX_ENTITIES * 3 * 4 * 2); // pos+vel, f32
// SAB 위에 매 직접 component 정의 (bitECS 0.4+ allows custom buffer)
const Position = {
x: new Float32Array(sab, 0, MAX_ENTITIES),
y: new Float32Array(sab, MAX_ENTITIES * 4, MAX_ENTITIES),
};
const Velocity = {
x: new Float32Array(sab, MAX_ENTITIES * 8, MAX_ENTITIES),
y: new Float32Array(sab, MAX_ENTITIES * 12, MAX_ENTITIES),
};
const world = createWorld();
// ... addEntity, addComponent (writes go into SAB views)
```
### Pattern 2: worker spawn + SAB share
```typescript
const N_WORKERS = 4;
const workers = Array.from({ length: N_WORKERS }, (_, id) => {
const w = new Worker("./physics-worker.ts", { type: "module" });
w.postMessage({ sab, workerId: id, n: N_WORKERS, maxEntities: MAX_ENTITIES });
return w;
});
```
### Pattern 3: physics system in worker
```typescript
// physics-worker.ts
self.onmessage = ({ data: { sab, workerId, n, maxEntities } }) => {
const px = new Float32Array(sab, 0, maxEntities);
const py = new Float32Array(sab, maxEntities * 4, maxEntities);
const vx = new Float32Array(sab, maxEntities * 8, maxEntities);
const vy = new Float32Array(sab, maxEntities * 12, maxEntities);
const stripe = Math.ceil(maxEntities / n);
const start = workerId * stripe;
const end = Math.min(start + stripe, maxEntities);
setInterval(() => {
const dt = 0.016;
for (let i = start; i < end; i++) {
px[i] += vx[i] * dt;
py[i] += vy[i] * dt;
}
}, 16);
};
```
### Pattern 4: barrier-synchronized frame
```typescript
// shared int32 frame counter
const sync = new Int32Array(sab, syncOffset, 4);
// sync[0] = workersReady, sync[1] = generation
function workerStep() {
// do work
doStripe();
// barrier
if (Atomics.add(sync, 0, 1) + 1 === N_WORKERS) {
Atomics.store(sync, 0, 0);
Atomics.add(sync, 1, 1);
Atomics.notify(sync, 1, N_WORKERS - 1);
} else {
const gen = Atomics.load(sync, 1);
Atomics.wait(sync, 1, gen);
}
}
```
### Pattern 5: read-only system on all workers
```typescript
// AI system: read pos/vel of others, write own intent → no contention
function aiSystem(workerId: number) {
for (let i = start; i < end; i++) {
let nearestX = 0, nearestY = 0, nearestDist = Infinity;
for (let j = 0; j < maxEntities; j++) {
if (j === i) continue;
const dx = px[j] - px[i], dy = py[j] - py[i];
const d = dx * dx + dy * dy;
if (d < nearestDist) { nearestDist = d; nearestX = px[j]; nearestY = py[j]; }
}
// write only own intent slot
intent[i] = computeIntent(px[i], py[i], nearestX, nearestY);
}
}
```
### Pattern 6: render thread on main, worker writes only
```typescript
// main thread: requestAnimationFrame → read SAB, render
function frame() {
for (let i = 0; i < activeCount; i++) {
ctx.fillRect(px[i], py[i], 2, 2);
}
requestAnimationFrame(frame);
}
// 매 race: workers writing while main reads — visual tearing 가능, 대부분 게임에서 허용.
// strict 의 매 double buffer (front/back) → flip on barrier.
```
### Pattern 7: double-buffered position
```typescript
const pxA = new Float32Array(sab, offA, max);
const pxB = new Float32Array(sab, offB, max);
let frontIdx = 0;
function workerStep() {
const front = frontIdx === 0 ? pxA : pxB;
const back = frontIdx === 0 ? pxB : pxA;
// read front, write back
for (let i = start; i < end; i++) back[i] = front[i] + vx[i] * dt;
// barrier → main flips frontIdx
}
```
### Pattern 8: SoA SIMD (WASM SIMD or manual unroll)
```typescript
// 매 4-wide unroll — JIT가 종종 SIMD화
for (let i = start; i < end; i += 4) {
px[i] += vx[i] * dt;
px[i + 1] += vx[i + 1] * dt;
px[i + 2] += vx[i + 2] * dt;
px[i + 3] += vx[i + 3] * dt;
}
```
### Pattern 9: spawn/kill queue (lock-free SPSC)
```typescript
// 매 main 만 spawn, worker 만 kill — single-producer queue
// 매 ring buffer of entity IDs, Atomics-driven head/tail
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| <1k entities | Single thread, 매 충분 |
| 1k10k, simple physics | bitECS single-thread |
| 10k+, heavy AI/physics | bitECS + SAB + worker pool |
| Render heavy | OffscreenCanvas worker |
| Voxel/chunk world | Per-chunk worker assignment |
**기본값**: 매 single thread first. 매 measure → SAB 매 4 worker 부터 의미 있을 때만.
## 🔗 Graph
- 부모: [[ECS]] · [[bitECS]] · [[Web Worker]] · [[SharedArrayBuffer]]
- 응용: [[Particle System]]
- Adjacent: [[Web Worker와 SharedArrayBuffer를 이용한 실제 고부하 병렬 처리 구현체 (실패_성공 포함)]] · [[OffscreenCanvas]] · [[가변적 LOD(Level of Detail) 시스템]]
## 🤖 LLM 활용
**언제**: 매 large-scale entity simulation in browser. 매 60fps 매 100k+ entity.
**언제 X**: 매 small game, 매 single-thread bitECS 충분 — 매 SAB 의 debug 비용 매 큼.
## ❌ 안티패턴
- **Anti1: 매 component write 매 worker 동시**: race. 매 ownership 명확히.
- **Anti2: 매 frame SAB 재생성**: GC 폭발. startup 1번.
- **Anti3: 매 worker 마다 component query**: query overhead 누적. 매 main 에서 ID list 한번 + worker 에 stripe.
- **Anti4: false sharing — 매 worker 가 인접 entity write**: 매 stripe 대신 매 mod 분산은 false sharing 위험. stripe 사용.
- **Anti5: render race 무시**: visual artifact. 매 double buffer or 매 tolerate.
## 🧪 검증 / 중복
- Verified (bitECS GitHub, 20252026 Web Worker SAB ecosystem).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — bitECS+SAB architecture + canonical merge |