earstrip, 3.7M 맵 폴리곤을 489ms에 삼각분할함 earcut보다 C++에서 14% 빠름
- earstrip은 지도 엔진의 폴리곤 삼각분할기를 ISC 라이선스의 C++ 헤더 하나로 공개한 라이브러리로, C++에서 earcut.hpp보다 14% 빠르고 브라우저에서는 earcut.js보다 1.4~2.1배 빠름
- 줌 레벨 13의 마스코비아 지도 폴리곤 3,740,425개를 기존 Delaunay 삼각분할기는 M4 Pro 한 코어에서 2.93초에 잘랐으나, ear clipping으로 바꾼 뒤 489ms에 처리함
- 면적 4개 이하 폴리곤이 180만 개로 전체의 거의 절반을 차지하는데, 기존 Delaunay 코드는 이들을 처음부터 새로 삼각분할하며 419ms를 씀
- 1975년 Gary Meisters가 증명한 바에 따르면 꼭짓점이 3개보다 많은 단순 다각형에는 겹치지 않는 귀(ear) 가 최소 2개 있어서, n개 꼭짓점 다각형이 n-2개 삼각형으로 나뉨
Hacker News 의견들
Claude Opus 5, 5.5 써보면 최적화 구현은 잘하는데 처음엔 단순하게 짜고 속도 얘기 나와야 손대더라. 글 문체도 'A GPU fills triangles and nothing else' 같은 거 보면 Claude 냄새 남.
Triangle이라는 프로그램 써봄. 지자체 쓰레기 수거 구역 색칠하는 데 몇 년째 쓰는데 빠르고 문제 없이 돌아감.
earcut 작성자인데 JS 버전은 번들 크기 때문에 최적화를 일부러 빼둠. 4.1k min/gz 유지가 목표였음. Mapbox GL JS에선 이 정도면 충분히 빠름. C++ 쪽 Mapbox는 작은 폴리곤은 earcut.hpp로, 크고 복잡한 건 monotone decomposition으로 넘김. WASM 빌드 크기가 궁금함.
earstrip 쪽에서 답하면, 분기 없는 dent count 덕분에 earcut을 이겼고 wasm이 그만큼 빠른 이유임. wasm 모듈은 gzip 27KB고 base64 래퍼 붙이면 npm 패키지에서 41KB임.
delaunay32 만든 사람인데 divide-and-conquer 방식이라 Delaunay 기준선이랑 비교해보고 싶음. 아직 벤치 안 돌려봤고 현재 API는 간단한 링에 겹치지 않는 구멍만 받음.
숫자 없으면 의미 없음. world.bin 56,472개 기준으로 earstrip 453.4ms, delaunay32 1696.9ms 나왔음. 257개 이상 큰 폴리곤 구간에선 376.8ms 대 1209.4ms임.
Seidel 방식 시도해봤는데 상수가 너무 크고 구현도 어려워서 포기함. 지도 데이터에선 earcut보다 느리고 덜 견고했음. 요즘은 LLM으로 검증 루프 돌리기 쉬우니 다시 해볼 만함.
earcut 직접 짜봤는데 엣지 케이스 다 잡는 게 진짜 고생임. 그래도 끝까지 돌아가는 거 보면 뿌듯함.
길고 얇은 삼각형은 GPU 래스터라이저엔 최악 아님? 근데 Nanite처럼 클러스터로 계층 컬링하는 엔진이면 얇은 삼각형이 화면을 가로질러서 스트리밍이랑 컬링을 망가뜨림.
균형 잡힌 삼각형으로 바꾸면 정점 수만 늘어남. GPU 메모리랑 버텍스 파이프라인 일만 늘고, 폴리곤이 작아서 컬링 이득도 없음.
삼각형 집착은 1995년쯤 MS가 DirectX에서 삼각형만 지원하기로 해서 생긴 거임. GPU 하드웨어도 그걸 따라가서 지금까지 이어짐.
면적만 필요하면 신발끈 공식으로 바로 구하면 됨. 점이 안에 있는지도 래스터라이저가 행렬식으로 수십억 번씩 체크하고 있음.