프로그래밍 언어에 대한 내 생각을 바꾼 글들
(bernsteinbear.com)- 프로그래밍 언어와 컴파일러에 대한 시각을 근본적으로 바꿔준 다양한 글, 논문, 동영상을 소개함
- 실용적인 GC 구현, 옵티마이저 설계, 레지스터 할당, 정규표현식 엔진 등에 대한 이해를 크게 넓혀준 자료들
- Z3와 추상 도메인, SSA 형식, E-Graphs 등 실무 알고리듬과 구조가 실제 코드 예시와 함께 쉽게 설명됨
- 각 자료는 복잡한 개념을 간결하면서도 확장 가능하고 이해하기 쉽게 풀어줌
프로그래밍 언어와 컴파일러에 관한 인식의 전환을 가져온 글들 소개
- 가끔씩 프로그래밍 언어와 컴파일러 관련 주제에 대해 내 생각을 완전히 바꿔주는 논문, 블로그 포스트, 영상 등을 발견함
- 몇몇 글의 경우 읽기 전에는 어떻게 생각했는지조차 기억이 안 날 만큼 강렬한 영향력을 받음.
- 아래는 그런 자료들에 대한 소개임 (순서 무관)
GC, 옵티마이저, 추상 도메인, 레지스터 할당 관련
- Andy Wingo의 a simple semi-space collector는 Cheney/복사/컴팩팅 가비지 컬렉터 개념을 이론에서 실제로 적용하는 과정을 잘 보여줌
- 본문의 GC 핵심 구현은 매우 간결하며, 확장 가능하고 한나절이면 이해할 수 있음
- CF Bolz-Tereick의 Implementing a Toy Optimizer 글은 옵티마이저에서 명령어 rewrite 방식에 대한 인식 전환을 이끔
- 단순한 찾기-치환 대신 forwarding pointer 사용을 강조하며, union-find 개념을 소개함
- 전체 toy optimizer 시리즈는 각 글마다 새롭고 흥미로운 내용을 담고 있음
-
A Knownbits Abstract Domain for the Toy Optimizer, Correctly 글은 새로운 추상 도메인과 Z3 활용법을 동시에 소개함
- Z3가 여러 수치 연산 증명에 이용되는 방식뿐 아니라, Python 코드 검증 엔진으로 활용되는 예시를 보여줌
- Z3가 반례를 못찾으면 코드의 정당성 보장이라는 아이디어를 소개함
- Chris Fallin의 Cranelift, Part 3: Correctness in Register Allocation에서는 입력마다 올바른 레지스터 할당을 직접 증명하는 방식을 설명함
- 프로덕션 환경에서는 옳은 할당이나 의미있는 크래시 중 하나를 얻게 됨
- 퍼징 기법으로 상태 공간을 탐색하고 버그를 탐지하는 접근을 도입함
파싱, 인터프리터, JIT, 추상구조 관련
- Russ Cox의 Regular Expression Matching: the Virtual Machine Approach는 정규표현식 엔진 구현을 약 50줄의 읽기 쉬운 코드로 제시함
- 이 과정에서 코루틴, 파이버, 스케줄러 등의 원리도 알기 쉽게 설명함
- Andrej Karpathy의 micrograd는 외부 라이브러리 없이 뉴럴 네트워크를 동작시키는 초소형 구현 예시로, 머신러닝의 기본 구조와 원리 습득에 도움이 됨
- Fil Pizlo의 How I implement SSA form은 union-find 구조를 개선하는 새로운 방법을 소개함
- SSA 변환에서 추가 포인터를 객체 내부 Identity tag로 관리하는 방식임
- 이외에 Phi/Upsilon form, TBAA 스타일 heap 효과 등 더 생각할 거리를 제공함
- Fil Pizlo의 Speculation in JavaScriptCore는 JavaScriptCore의 다양한 옵티마이저 구현 방식을 상세히 다룸
- 글을 다시 읽을 때마다 새로운 인사이트를 얻게 됨
컴파일러 설계, 파서, IR 구조, E-Graphs
- Chandler Carruth의 Modernizing Compiler Design for Carbon Toolchain 발표(29분 즈음)에서는 압도적으로 빠른 컴파일 타임 목표 수립과 전체 구조 설계 과정을 설명함
- 40분 즈음부터 각 계층별로 구조를 풀어서 설명함
- Allison Kaptur의 A Python Interpreter Written in Python은 CPython 내부 바이트코드 인터프리터 작동 원리를 쉽게 이해하게 해줌
- Eli Bendersky의 Parsing expressions by precedence climbing는 전통적인 재귀하강 파서보다 이해가 쉽고 개발 부담이 작은 Precedence Climbing 파싱법을 소개함
- Takashi Kokubun의 Ruby JIT Challenge는 코드 생성과 새로운 레지스터 할당 방법(stack folding at compile-time)을 보여줌
- Abdulaziz Ghuloum의 [An Incremental Approach to Compiler Construction (PDF)(https://bernsteinbear.com/assets/img/11-ghuloum.pdf)은 기존 다단계 컴파일러 설계를 한 번에 이해할 수 있는 단일 패스 구현 방식을 설명함
- 각 기능을 엔드 투 엔드로 차근차근 추가하는 방식을 취함
- Fernando Borretti의 Lessons from Writing a Compiler는 컴파일러 구현 전략을 명확하게 언어화해서 설명함
-
egg: Fast and extensible equality saturation 논문은 옵티마이저 및 패스 순서에 대한 인식을 근본적으로 변화시킴
- 표현식의 모든 가능한 버전을 압축된 하이퍼그래프로 만들어 두고 최적의 버전을 선택하는 사고법을 제시함
- Chris Fallin의 Cranelift: Using E-Graphs for Verified, Cooperating Middle-End Optimizations는 실제 상용 컴파일러에서도 e-graphs가 효과적으로 작동함을 입증함
- Phil Zucker의 Acyclic Egraphs and Smart Constructors는 무환형 e-graph 구조와 스마트 생성자 활용을 탐구함
- 초기에는 이해가 어려웠지만 시간이 지나면서 점차 이해가 깊어지는 글임
AST 저장, 대규모 병렬 동적 해석 등 기타
- Bob Nystrom의 이 Reddit comment와 Adrian Sampson의 Flattening ASTs는
- AST를 거의 바이트코드처럼 컴팩트하게 저장하는 방법과,
- IR 노드를 이런 식으로 저장하면 대규모 병렬 락프리 해석도 가능하다는 큰 논의를 이끌어냄
- Cliff Click의 버퍼 할당 속도 관련 언급도 이러한 사고에 영향을 주었음
Hacker News 의견
-
나는 이 글이 정말 마음에 듦, 최근에 컴퓨터 과학 연구를 많이 했지만 여기서 언급된 것 중에 아직 접해보지 못한 것도 있음, 내가 좋아하지만 여기 없는 논문들을 몇 개 소개하고 싶음: Ian Piumarta의 “Open, Extensible Object Models”는 프로그래머에게 최대한의 자유를 주는 최소한의 객체지향 메타오브젝트 시스템에 대해 다룸, 기본적으로 메시지 전송 연산만 정의하고 나머지 모든 것은 런타임에 변경 가능함, “Art of the Metaobject Protocol”의 실용적인 버전 느낌임, John Ousterhout의 “Scripting: Higher-Level Programming for the 21st Century”는 시스템 프로그래밍 언어와 스크립팅 언어의 이분법에 대해 다룸, 우리는 모든 걸 빠르고 생산성 있게 할 수 있는 완벽한 다중 패러다임 언어를 늘 원하지만, 컴파일되는 빠르고 복잡한 시스템 언어가 편리하고 유연한 인터프리터형 프론트엔드와 조합될 때 더 나을 때가 많음, 사실 간단히 C와 Tcl만 같이 써도 충분할 때가 많음, 프로그래밍 언어를 만드는 사람이라면 꼭 읽어야 할 글임, Niklaus Wirth의 Project Oberon은 고수준 UI부터 커널, 컴파일러, RISC 비슷한 CPU 아키텍처까지 전체 컴퓨터 시스템을 구현한 사례임, 그는 “lean software”를 위한 강력한 청원을 했고 실제로 실천함, 요즘처럼 의존성 지옥과 과도한 추상화가 난무하는 시대에선 잃어버린 장인정신임
- Ousterhout의 이분법과 결론에는 동의하지 않음, 그의 요지는 언어가 시스템 언어(C) 아니면 스크립트 언어(Tcl, Python) 중 하나라는 것임, 시스템 언어는 강한 타입이고 자료구조/알고리즘 용, 스크립트 언어는 타입이 없어서 '붙이기' 용이라는 주장임, 스크립트 언어가 '타입이 없음' 덕분에 더 간결하고 빠른 개발이 가능하다고 주장하지만, 사실 이는 현실적인 설명이 아니라고 생각함, 예로 Tcl 코드와 C++/MFC 코드를 비교하며 Tcl이 더 좋다고 언급하는데, 사실 이는 구문(Syntax)이 더 나아서 좋아한다는 것일 뿐임, 타입이 없는 언어가 빨라진다는 주장은 사실이 아님, 제한을 언제 마주치냐의 차이일 뿐임, 타입 에러를 실행 전에 모두 확인하는 게 더 좋고, 모든 언어에 정적 타입 분석이 가능하지만 그게 복잡하고 어렵기 때문임, PL(프로그래밍 언어) 설계자로서 런타임에만 타입 체크하는 건 쉽게 언어를 만들기 위한 타당한 결정이긴 하지만, 그것이 더 나은 선택이란 건 아님
-
나는 댓글을 즐겨찾기 할 수 없어서 글 남김
-
이 글이 정말 마음에 듦, 프로그래밍 언어에 대한 글이 내가 프로그래밍 자체를 바라보는 방식을 바꿔줌, TAPL(Types and Programming Languages)의 “안전성”에 대한 인용구를 자주 떠올리게 됨, 안전한 언어란 프로그래머가 발등을 찍지 못하도록 막아주고, 자신의 추상화를 보호하는 언어임, 즉 언어가 제공하는 추상화와 프로그래머가 만들어내는 상위 추상화의 무결성을 보장해주는 능력이 중요함, 예를 들어 배열이란 추상화가 있다면, 명시적으로 업데이트할 때만 변경 가능해야 하고, 다른 데이터 구조를 잘못 건드려도 안 된다는 식임
-
흥미로운 개발 습관에 대해 말하자면… APL로 유명한 Aaron Hsu는 생각을 정리할 때 만년필로 캘리그래피 방식으로 코드를 씀, 나는 비슷하게 싸구려 볼펜으로 파이썬 객체의 플로우차트 같은 걸 그리면서 생각을 정리함, 일종의 저렴이 UML임
-
나도 가장 어려운 문제를 다룰 땐 만년필을 찾게 됨, 만년필을 쓰면 완전히 다른 사고 공간에 들어가는 느낌임, 편집 한계가 있어서 더 일관성 있고 선형적인 사고가 유도되지만, 영어, 코드, 수학, 다이어그램 등을 자유롭게 오갈 수 있어서 창의성이 열림
-
손글씨와 기억력 향상은 실제로 연관이 입증되었음, 컴퓨터로 필기하는 건 손잡이에 지문 남기는 거랑 비슷한 수준임, OCR 기술이 정말 좋아져서 완벽하게 손글씨로만 기록해도 저장과 검색이 가능해지길 바람
-
-
Rich Hickey의 강연(특히 초기 강연들)을 꼭 보길 추천하고 싶음, 나도 그런 강연을 보고 프로그래밍 자체를 바라보는 시각이 완전히 달라졌음
-
나한텐 Larry Wall의 “Programming Perl”과 함께 Rich Hickey의 강연들이 가장 영향력이 컸음
-
“Simple made easy” 강연은 지난 10년간 모든 컨퍼런스 연사들이 인용해대서 이제는 클리셰가 됐기 때문에 건너뛰라는 농담도 하고 싶음, 개인적으로는 “Hammock driven development”가 더 좋지만 회사에서 권장하긴 부족함
-
-
Abdulaziz가 쿠웨이트로 돌아간 후 조용해진 게 아쉬움, 그는 2009년에 Maxine VM 인턴이었고 정말 좋은 사람이었음, 그 논문은 진짜 보석임
- 나도 아쉬움, 하지만 그가 최근에 빵집을 차려서 사업이 잘 되고 있는 것 같음, 그런 면에선 꿈을 이루고 있는 셈임
-
인터프리터를 고속화하는 closure 기반 인터프리터에 대한 좋은 글이 최근에 있었음, 나는 그 기법을 써서 간단한 brainfuck 인터프리터를 만들어 봤고 꽤 빨랐음, 다른 곳에서 쓸 일은 없겠지만 실험 삼아 해본 건 유익했음
- closure 배열과 함수 포인터-데이터가 번갈아 들어있는 배열의 차이가 궁금함, 후자는 대부분 언어에서 자연스럽지 않고 C 같은 언어에서만 어울림, 그러나 정적 함수와 데이터를 배열에 같이 두면 캐시 친화성이 더 좋을 것이란 생각이 듦
-
JavaScript나 .NET 같은 상위 레벨 언어에 대해 이런 글이 나왔으면 좋겠음, 이 작성자는 매우 똑똑한 분이지만 대부분 사용자들보다 더 저수준(혹은 고수준?)에서 활동 중임
-
그의 블로그 다른 글들도 정말 훌륭함
-
micrograd 관련: Github 저장소의 소스코드 말고 더 많은 문서가 있는지 궁금함
- Andrej Karpathy가 만든 마이크로그래드 개발 과정을 다루는 유튜브 시리즈가 있음
-
이 사람을 좋아해서 하는 말이지만, 여기 있는 글은 PL(프로그래밍 언어) 자체에 관한 게 아니고 거의 다 컴파일러에 관한 내용임(가비지 컬렉터 제외), 물론 컴파일러도 좋아하지만, PL 주제랑은 별개임
- 프로그래밍 언어(구현)라는 의미 아닐까?