⚡ 성능 최적화 및 대기열 조절 엔진
Agrarian Reform은 대규모 서버에 최적화되어 대형 농장을 운영해도 순간적인 렉이나 TPS 하락이 발생하지 않습니다.
📊 성능 사양 인포박스
| Property | Value |
|---|---|
| Global Throttling Budget | CROPS_PER_TICK = 5 |
| Queue Implementation | java.util.concurrent.ConcurrentLinkedQueue |
| Sub-Chunk Palette Filter | hasOnlyAir() & maybeHas(AgrarianCropRules::isCropBlock) |
| 수분 탐색 알고리즘 | 체비쇼프 동심원 탐색 ($r=1 \to \text{maxRange}$, 인접한 물 근원 즉시 완료) |
| 신발 검사 최적화 | 맨발 즉각 판정 ($0.0001\mu\text{s}$, 복잡한 NBT 마법부여 순회 생략) |
| 진단 로그 출력 | 임시 게임 규칙 agrarian_reform:debug_mode로 제어되는 정적 SLF4J 로거 |
🧠 아키텍처 설계 및 고속 검사 파이프라인
┌─────────────────────────────────────────────────────────────┐
│ CHUNK LOAD SCAN EVENT │
│ Palette Pre-Filter: section.hasOnlyAir() & maybeHas() │
│ Rejects 85%+ empty non-crop sub-chunks in O(1) time │
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌──────────────────────────────┴──────────────────────────────┐
│ ConcurrentLinkedQueue<CropUpdateTask> │
│ Lock-free thread-safe task buffer │
└──────────────────────────────┬──────────────────────────────┘
│
▼
┌──────────────────────────────┴──────────────────────────────┐
│ ServerTickEvents.END_SERVER_TICK │
│ Polls at most 5 tasks per tick │
│ Updates block states smoothly across consecutive game ticks │
└─────────────────────────────────────────────────────────────┘왜 1틱당 5작물인가요?
플레이어가 10,000개의 작물이 심어진 농장을 24시간 언로드한 뒤 복귀했을 때, 한 번의 틱에 10,000개의 블록을 한꺼번에 업데이트하면 1000ms가 넘는 치명적인 멈춤이 발생합니다.
락프리 방식으로 1틱당 5작물씩 나누어 계산함으로써:
- 청크가 로드되는 동안에도 서버는 안정적인 20 TPS를 유지합니다.
- 10,000개의 작물은 백그라운드에서 2,000틱(약 100초) 동안 부드럽게 성장을 따라잡습니다.
🏎️ 핵심 고속 검사 및 알고리즘 최적화
- 서브청크 팔레트 빠른 통과: 청크당 $98,304$개 좌표를 모두 확인하는 대신, $16 \times 16 \times 16$ 팔레트를 검사합니다. 농작물이 없는 구역은 $0.0001\mu\text{s}$ 만에 통과합니다.
- 체비쇼프 동심원 탐색: 안쪽 사각형 고리($r = 1 \to \text{maxRange}$)부터 검사합니다. 대부분의 농토는 물이 바로 인접해 있어($r=1$) 첫 번째 고리에서 즉시 탐색이 종료됩니다.
- 맨발 짓밟기 고속 통과: 개체가 경작지를 밟으면 먼저 발 슬롯이 비었는지 확인합니다. 신발이 없으면 번거로운 NBT 마법부여 확인을 완전히 건너뜁니다.
- 최대 성장 시 조기 탈출: 가속 성장 루프 중 작물이 최대 단계에 도달하면 즉시 연산을 종료하여 불필요한 블록 쓰기 작업을 방지합니다.
💾 0-디스크 기록 보장 및 더티 상태 보존
- 읽기 전용 청크 스캔: 초기 청크 검사는 순수 읽기 전용이므로 청크의
unsaved플래그는false상태로 유지됩니다. - 선택적 블록 갱신:
ContinuumManager.processCropUpdate에서는 실제 단계 상승 $\Delta \text{age} > 0$이 발생할 때만 블록을 갱신합니다. - 불필요한 디스크 쓰기 방지: 변경이 없는 청크는
unsaved == false를 유지하므로 바닐라 자동 저장이 NBT 변환과 디스크 저장을 건너뜁니다($0\text{ 디스크 I/O}$).
See also: 컨티넘 (오프라인 성장 지속), 유체역학 및 고급 관개 시스템, and 아키텍처 및 Mixin 주입 대상.
