Nix가 내 디버거의 절반을 만들어 줬다

1 hour ago 3

Rewind VM은 스레드 스케줄까지 입력으로 결정되는 결정론적 VM으로, Nix 빌드의 경쟁 상태를 재현하고 분석함. 디버거에 필요한 입력, 소스, 디버그 심볼을 다른 머신에서도 확보하는 기반은 이미 Nix가 제공함 rewind check 는 스레드 스케줄을 바꿔 빌드를 반복하고, 성공과 실패를 가르는 재스케줄링 지점을 한 단계까지 좁힘. 은행 계좌 예제에서는 노트북에서 11초 만에 해당 지점을 찾음 소스 패널과 gdb 연동으로 실행 단계별 소스, 호출 스택, 모든 스레드의 상태를 조사할 수 있음. gdb는 기록에서 분기한 실행에 붙으므로 원본 기록을 바꾸지 않음 실행 비교와 스레드 타임라인은 두 실행이 처음 달라지는 이벤트와 각 단계의 CPU 점유 스레드를 보여줌. 결정론적 재생 덕분에 별도 기록 없이 이벤트 사이의 실행 순서도 복원할 수 있음 “Check from here”는 기존 실행의 임의 단계에서 여러 스케줄로 분기해 결과가 얼마나 달라지는지 확인함. 은행 예제에서는 원본 실행이 성공했지만, 특정 단계에서 분기한 16개 변형 스케줄은 모두 실패함 결정론적 실행과 Nix의 역할 Rewind VM은 Nix 빌드 실행을 입력의 순수 함수로 만들며, 스레드 스케줄도 여기에 포함됨 Nix 빌드의 여러 경쟁 상태를 찾고 재현하고 해결하는 과정에서 소스 패널, 스택 프레임, 북마크, Compare 탭, gdb 지원, 스레드별 타임라인, “Check from here” 기능이 추가됨 디버거에는 프로그램의 정확한 입력, 디버그 심볼, 프로그램과 하위 라이브러리의 소스, 다른 머신에서도 이를 확보할 수단이 필요함 Nix derivation이 이러한 기반을 제공해, 새 기능을 구현할 때 어려운 부분 상당수가 이미 해결돼 있었음 두 스레드가 한 계좌에 입금할 때 bank 예제의 deposit 함수는 잔액을 읽고, 장부에 한 줄을 쓴 뒤, 읽어 둔 잔액에 입금액을 더해 저장함 한 스레드의 읽기와 저장 사이에 다른 스레드가 입금하면, 오래된 잔액을 바탕으로 한 저장이 다른 입금 결과를 덮어씀 16코어 노트북에서는 1,000회 중 396회 잔액 손실이 발생했지만, taskset으로 단일 코어에 고정하면 1,000회 모두 손실이 없었음 단일 코어에서는 입금 도중 스레드가 전환되는 일이 드물기 때문에 Rewind는 스케줄을 의도적으로 교란함 Rewind VM도 CPU가 하나여서 첫 실행은 성공했지만, rewind check --w...

Read Entire Article