작가의 말
맥카시(McCarthy)와 콜린(Collins)이 작성한 동적 자동화 메모리 관리(즉, 가비지 컬렉션)에 관한 첫 번째 논문의 50주년이 되는 해에 이 책의 집필이 거의 완료돼 그 기념일을 축하할 따름이다. 가비지 컬렉션은 리스프(Lisp) 프로그래밍 언어에서 처음 도입됐다. 이상한 우연이지만, 1958년에 시작된 리스프의 구현 이후로 정확히 40년이 되는 1998년 10월, 메모리 관리에 관한 첫 번째 국제 심포지엄의 10주년 기념에 관한 글을 쓰기 시작했다. 맥카시는 첫 번째 온라인 시범이 MIT 산업 관련 심포지엄에서 있었다고 회고했다. 좋은 인상을 남기는 것이 중요했지만, 불행히도 시범 중간에 IBM 7041은 자신의 32k 워드 메모리 전체를 소진하고서(맥카시 팀은 바로 전의 리허설에서 리스프 코어 이미지를 리프레시하는 것을 잊어버렸다) Flexowriter는 초당 10 문자를 인쇄하는 데 그쳤고, 이로 인해 시연의 남은 시간을 모두 사용해버렸다. 맥카시와 청중들은 폭소를 터트릴 수밖에 없었다(실제로 다음 문장만 출력하고 시연이 끝나버렸다. -옮긴이
출판사 서평
★ 이 책에서 다루는 내용 ★
■ [Garbage Collection](1996)의 후속으로 완벽한 최신의 독보적인 개정판
■ 병렬적, 병행적, 실시간 가비지 컬렉션 알고리즘을 철저히 분석
■ 런타임 시스템 인터페이스를 비롯해 가비지 컬렉션의 까다로운 면을 설명
■ 2,500 종류가 넘는 가비지 컬렉션 관련 문서가 담긴 포괄적인 온라인 데이터베이스에 의한 지원
★ 이 책의 대상 독자 ★
이 책에는 지난 50년간에 걸친 자동 메모리 관리 연구자와 개발자들이 축척한 다양한 경험을 함께 수록하려 노력했다. 문헌은 방대해 우리가 제시한 온라인 참고 문헌은 이 책의 집필 당시에 2,500 항목 정도였다. 가장 중요한 접근법과 최신 기술을 하나의 접근 가능한 프레임워크 내에서 논의하고 비교한다. 일관적인 스타일과 용어를 사용해 알고리즘과 개념을 제시함에 있어서 신중을 기했다. 이들 알고리즘과 개념은 종종 의사코드와 예시를 통해 자세하게 설명한다. 성능이 중요시되는 곳에서는 동기화를 위한 기본 연산의 선택과 캐시 같은 하드웨어 요소가 알고리즘 설계에 영향을 주는 것과 같은 저수준(Low level)의 세부 사항에 주의를 기울였다.
특히 지난 10여 년간에 걸쳐 하드웨어와 소프트웨어 향상으로 인해 가비지 컬렉션에 주어진 새로운 도전적 과제를 언급한다. 프로세서와 메모리 간의 성능 간극은 대체로 계속 커지고 있다. 프로세서 클럭 속도는 증가했고 더 많은 코어가 프로세서에 위치하며, 다수의 프로세서 모듈을 가진 구성이 일반화됐다. 고성능 가비지 컬렉터의 설계자와 구현가들을 위해 이런 변경의 결과에 대해 중점을 둔다. 이들의 알고리즘은 캐시 성능이 중요시되므로 지역성을 고려해야 한다. 늘어난 애플리케이션 프로그램들은 멀티코어 프로세서에서 멀티스레드화된 멀티코어 프로세서에서 실행된다. 순차적 병목현상을 회피하게끔 메모리 관리자를 설계해야 한다. 반면 새로운 하드웨어가 제공하는 병렬성을 이용할 수 있게 가비지 컬렉터를 설계해야 한다.
Jones[1996]는 당시에 여러 개의 컬렉터 스레드를 병렬로 실행할 수 있을지에 대해서는 전혀 고려하지 않았다. 집필 당시에는 생소하게 보였던 점진적 수집과 병행적 수집에 관해 한 단원을 할애한다.
현대 하드웨어가 제공하는 가능성과 제약은 이 책 전반에 걸쳐 민감한 부분이다. 이 책 전체에 걸쳐 지역성 문제를 다룬다. 시작 부분부터 애플리케이션 프로그램은 멀티스레드화될 수 있음을 가정한다. 좀 더 단순하고 전통적인 알고리즘을 많이 다루겠지만, 병렬성과 점진적, 병행성, 실시간 가비지 컬렉션 논의에 이 책의 절반을 할애한다. 이러한 내용들이 프로그래밍 언어 구현에 관심이 있는 대학원생과 연구자, 개발자에 도움이 될 것을 희망한다. 프로그래밍 언어와 컴파일러 구축, 소프트웨어 엔지니어링, 운영체제의 고급정을 수강하는 학부생에게도 이 책은 유용하다. 더욱이 여기서 제공하는 지식을 통해 전문적 프로그래머에게도 가비지 컬렉터가 직면한 문제와 상이한 컬렉터가 동작하는 방식에 좀 더 나은 통찰력을 제공해 여러 언어가 제공하는 가비지 컬렉터를 선택하고 구성하는데 있어서 좀 더 진보가 있기를 희망한다. 현대 프로그래밍 언어가 거의 채택하고 있는 가비지 컬렉션의 완전한 이해는 모든 프로그래머에게는 필수적이다.
★ 이 책의 구성 ★
2장에서는 자동 저장 공간 회수가 바람직한 이유를 설명하고, 상이한 가비지 컬렉션 전략을 비교할 수 있는 방법을 소개한다. 이 책 전반에 걸쳐 사용되는 추상화와 의사코드 표기법의 설명으로 끝을 맺는다.
3장에서 6장까지는 고전적인 가비지 컬렉션을 구성하는 부분들을 상세히 다룬다. 마크 스윕과 마크 컴팩트, 복사 가비지 컬렉션, 참조 카운팅을 살펴본다. 현대 하드웨어에서 이들 구현에 특히 초점을 맞춰 이들 전략을 좀 더 심도 있게 다룬다. 좀 더 일반적인 소개를 원하는 독자는 이전에 출판된 『Garbage Collection: Algorithms for Automatic Dynamic Memory Management』(Wiley, 1996)을 참고하기 바란다. 7장에서는 2장에서부터 5장에 걸쳐 다룬 전략과 알고리즘에 대해 이들의 장점과 약점, 다른 컨텍스트에서의 적용 가능성을 좀 더 심도 있게 비교한다.
저장 공간이 회수되는 방식은 저장 공간이 할당되는 방식에 좌우된다. 7장에서는 메모리 할당의 상이한 방법을 고려해보고, 자동 가비지 컬렉션이 할당자의 정책(명시적 malloc/free 메모리 관리와는 다른 정책)에 영향을 주는 정도를 검토해본다.
1장에서 7장까지는 힙 내의 모든 객체는 동일한 방식으로 관리된다는 암묵적인 가정을 한다. 하지만 이런 가정이 왜 취약한 설계인지에 대해서는 여러 이유가 있다. 8장부터 10장까지는 힙을 다른 공간으로 분할하는 이유와, 이들 분할된 공간을 관리하는 방법을 고려해본다. 객체 관리에 가장 성공적인 전략 중 하나인 세대별 가비지 컬렉션을 살펴보고 대규모 객체와 기타 여러 분할 기법을 다루는 방법을 알아본다.
런타임 시스템의 나머지 부분과의 인터페이스는 컬렉터 구축의 가장 까다로운 부분이다.
11장을 포인터 찾기와, 수집하기에 안전한 지점, 읽기 및 쓰기 장벽을 비롯한 런타임 인터페이스에 할애했고, 12장을 최종화와 약한 참조 같은 언어 특정적인 관심 사항에 할애했다.
이제 관심사를 병행성으로 돌려보자. 13장에서는 현대 하드웨어가 가비지 컬렉션 구현가에게 제공하는 것을 조사해보고, 동기화와 진행, 종료, 의견 수렴에 대한 알고리즘을 살펴본다. 14장에서는 모든 애플리케이션 스레드가 중지된 동안에 병렬적으로 다중 컬렉터 스레드를 실행하는 방법을 알아본다. 15장에서부터 18장까지는 광범위한 병행적 컬렉터를 고려해보고, 사용자 프로그램에 가장 짧은 간섭을 가지면서 수집이 일어날 수 있도록 스레드 중지 방식의 요건을 완화한다. 마지막으로 19장에서는 이런 요건을 가장 도전적인 극한 상황인 경성 실시간 시스템용의 가비지 컬렉션으로 확장해본다.
각 장의 마지막 부분에 고려할 사항을 요약해뒀다. 이는 독자들로 하여금 자신들의 시스템이 갖는 요건이 무엇이며, 이들 요건을 어떻게 충족시킬지에 대한 질문을 불러일으키기 위해 의도한 것이다. 클라이언트 프로그램의 동작과 이들의 운영체제, 하부의 하드웨어에 관한 질문에 대해 해답을 주지는 않았다. 이들 요약 사항은 해당 장을 읽는 것을 대신하지는 못한다. 요약 사항은 압축한 해결책을 의도한 것이 아니며, 추가적인 분석에 논의의 초점을 두고자 함이다.
마지막으로, 빠진 부분은 무엇일까? 런타임 시스템에 장착된 메모리 관리의 자동 기법만 을 고려했다. 따라서 언어 명세에 가비지 컬렉션이 적시돼 있는 경우라도 이들 언어가 지원할 수도 있는 메모리 관리에 관한 다른 메커니즘을 심도 있게 논의하지 못했다. 가장 분명한 예는 ‘영역’의 사용인데, 이는 자바의 실시간 명세에서 가장 두드러지게 사용됐다. 영역 추론 문제나 스택 할당 문제에 잠시 관심을 기울였지만, 가비지 컬렉션을 대체하거나 최소한 이를 보조할 의도의 여타 컴파일 시점의 분석은 전혀 하지 못했다. 클라이언트 프로그램에서 참조 카운팅 같은 기법을 최적으로 사용하는 방법이 C++ 같은 언어에서 인기가 많을지라도 이를 언급하지 하지 않았다. 마지막으로, 지난 10년 동안에는 분산 가비지 컬렉션에서 새로운 연구가 거의 없었다. 다방면으로 이는 안타까운 일이다. 그 분야에서 배울 내용들이 매우 비일관적인 메모리 아키텍처에서 이질적인 수집을 하는 차세대 머신을 위한 컬렉터 개발에 유용할 수도 있었기 때문이다. 그럼에도 불구하고 분산 가비지 컬렉션을 언급하지 않았다.
THE GARBAGE COLLECTOR HAS BEEN CALLED. SOME INTERESTING
STATISTICS ARE AS FOLLOWS: (가비지 컬렉터가 호출됐으며, 일부 흥미 있는 통계치는 다음과 같다:)
50년이 지난 지금, 가비지 컬렉션은 더 이상 조롱거리가 아니며 현대 프로그래밍 언어 구현의 필수적 요소가 됐다. 실제로 비주얼 베이직(1991년 소개됨)은 1990년 이래로 개발된 언어 중에서 자동 메모리 관리를 채택하지 않은 채 가장 광범위하게 사용되는 언어일 것이 다. 하지만 그 후속인 VB.NET(2002)은 마이크로소프트의 공통 언어 런타임에 있는 가비지 컬렉터에 의존한다.
가비지 컬렉션이 이뤄지는 언어가 소프트웨어 개발에 제공하는 장점은 다양하다. 회수된 메모리를 여전히 참조하는 댕글링 포인터를 따라가거나, 이를 다른 컨텍스트에서 재사용하려는 것과 같은 더욱 나쁜 전반적인 버그를 없애준다. 이미 해제된 메모리를 해제하는 것은 더 이상 용납되지 않는다. 메모리 누수와 관련된 오류를 모두 방지하지는 못할지라도 프로그램의 메모리 누수 가능성을 줄여준다. 병행성 자료 구조의 구축과 사용을 매우 단순화시켜준다. 무엇보다도 가비지 컬렉션이 제공하는 추상화는 좀 더 뛰어난 소프트웨어공학적 관례를 제공한다. 사용자 인터페이스를 단순화해 이해와 유지 보수가 쉬운 코드의 생성이 가능하며, 그 결과로 좀 더 신뢰할 만해진다. 인터페이스에서 메모리 관리 걱정을 없앰으로써 재사용이 좀 더 쉬운 코드를 생성할 수 있다.
메모리 관리 분야는 소프트웨어와 하드웨어 양 측면에서 최근에 급속도로 향상됐다. 디지털 사의 알파칩에 기반을 둔 고사양 워크스테이션이 266MHz 속도를 지녔지만, 1996년에 인텔 펜티엄 프로세서는 120MHz의 클록 속도를 보였다. 최신 고사양 프로세서는 3GHz를 상외하며, 멀티코어 칩이 주류를 이룬다. 채용된 주 메모리의 크기는 거의 1000배까지 증가했으며, 데스크톱 머신의 일반적인 메모리 크기는 수 메가바이트에서 4기가바이트에 이른다. DRAM 메모리의 성능 향상은 이들 프로세서에 비해 크게 뒤떨어지지 않는다.
그 당시에 가비지 컬렉션은 모든 메모리 관리 문제에 대한 만병통치약이 아니라고 적시했고, 특히 경성 실시간 프로그램(마감 시한이 실패 없이 지켜져야 한다)에서 가비지 컬렉션의 문제는 아직 해결되지 않았다고 언급했다. 하지만 오늘날 경성 실시간 컬렉터는 이제 실험실에서 벗어나 상업적으로 시스템에 채택되고 있다. 현대 가비지 컬렉터 구현에서 많은 문제가 해결되었을지라도 새로운 하드웨어와 새로운 환경, 새로운 애플리케이션은 메모리 관리에 관한 새로운 연구 과제를 던져준다.
★ 옮긴이의 말 ★
프로그램 분야가 많지만 항상 그 기저에는 자원의 효율성이라는 대전제를 바탕으로 하고 있다. 컴퓨팅 분야의 역사에서 언제나 그랬듯이 가장 핫한 관심 대상인 분야는 메모리였고, 지금도 그럴 것이다. 하드웨어적 기술과 소프트웨어 동작 방식 또한 메모리 사용의 효율성에 기반을 두고 기술 향상이 이뤄졌음은 당연하다. 소프트웨어 측면에서 자동 메모리 관리 기법의 가장 핵심에 자리 잡고 있는 분야가 바로 가비지 컬렉션이다.
이 책에서는 전통적으로 가비지 컬렉션이 수행하는 작업과 알고리즘을 먼저 소개한다. 그러고 나서 좀 더 도전적인 사항들을 소개한다. 현대의 고성능 가비지 컬렉션 설계를위해 필요한 멀티코어 프로세서 모듈에 장착된 캐시 아키텍처를 고려한 알고리즘을 소개하며, 이와 더불어 새로운 하드웨어가 제공할 수도 있는 병렬성을 이용할 수 있는 컬렉터 설계에 대한 기본 지식도 제공한다. 그리고 최근 많은 임베디드 시스템에서 사용되는 실시간 시스템에서의 가비지 컬렉션에 필요한 요구 조건과 그 충족 방법을 제시한다.
최신 컴퓨터 시스템 아키텍처 또한 가비지 컬렉션과 연동하며, 근래의 모든 프로그래밍 언어는 가비지 컬렉션을 고려한 설계가 이뤄져 있고, 컴파일러 최적화 기법 또한 가비지 컬렉션과 연동한다. 현재 프로그래머이고 또한 전문적인 프로그래머를 꿈꾸는 누구라도 그 기저에서 동작하는 자동 메모리 자원 관리의 원리를 이해하고 구현 방식을 파악하며, 더 나아가서 도전적인 가비지 컬렉션을 설계하고 프로그래밍 언어 설계를 희망하는 사람이라면 이 책은 그 앞길에 한 줄기 빛이 될 것이라고 확신한다.