108 điểm bởi GN⁺ 2025-05-15 | 1 bình luận | Chia sẻ qua WhatsApp
  • Giới thiệu nhiều bài viết, luận văn và video đã thay đổi tận gốc góc nhìn về ngôn ngữ lập trìnhtrình biên dịch
  • Đây là những tài liệu đã giúp mở rộng đáng kể hiểu biết về cách triển khai GC, thiết kế optimizer, phân bổ thanh ghi, regex engine theo hướng thực dụng
  • Các khái niệm như Z3 và abstract domain, dạng SSA, E-Graphs được giải thích dễ hiểu cùng với ví dụ mã thực tế
  • Mỗi tài liệu đều diễn giải các khái niệm phức tạp theo cách ngắn gọn, có thể mở rộng và dễ nắm bắt

Giới thiệu những bài viết đã làm thay đổi nhận thức về ngôn ngữ lập trình và trình biên dịch

  • Thỉnh thoảng tôi lại bắt gặp những bài báo, bài blog hoặc video khiến cách nghĩ của tôi về các chủ đề liên quan đến ngôn ngữ lập trình và trình biên dịch thay đổi hoàn toàn
  • Với một vài bài, ảnh hưởng mạnh đến mức tôi thậm chí không còn nhớ trước khi đọc mình đã nghĩ thế nào nữa.
  • Dưới đây là phần giới thiệu những tài liệu như vậy (không theo thứ tự nào)

Về GC, optimizer, abstract domain và phân bổ thanh ghi

  • Andy Wingo với a simple semi-space collector cho thấy rất rõ cách áp dụng khái niệm Cheney/copying/compacting garbage collector từ lý thuyết vào thực tế
    • Phần cài đặt GC cốt lõi trong bài rất ngắn gọn, có thể mở rộng, và chỉ cần nửa ngày là có thể hiểu được
  • Bài Implementing a Toy Optimizer của CF Bolz-Tereick đã làm thay đổi cách nhìn về phương pháp instruction rewrite trong optimizer
    • Thay vì tìm-thay đơn thuần, bài viết nhấn mạnh việc dùng forwarding pointer và giới thiệu khái niệm union-find
    • Toàn bộ series toy optimizer đều chứa những ý tưởng mới mẻ và thú vị trong từng bài
  • Bài A Knownbits Abstract Domain for the Toy Optimizer, Correctly đồng thời giới thiệu một abstract domain mới và cách tận dụng Z3
    • Không chỉ cho thấy cách Z3 được dùng để chứng minh nhiều phép toán số học, mà còn minh họa việc dùng nó như một engine kiểm chứng mã Python
    • Bài viết giới thiệu ý tưởng rằng nếu Z3 không tìm được phản ví dụ thì có thể xem như có đảm bảo tính đúng đắn của mã
    Quảng cáo
  • Trong Cranelift, Part 3: Correctness in Register Allocation của Chris Fallin, tác giả giải thích cách trực tiếp chứng minh việc phân bổ thanh ghi là đúng với mọi đầu vào
    • Trong môi trường production, kết quả sẽ là hoặc phân bổ đúng hoặc crash có ý nghĩa
    • Bài viết đưa vào cách tiếp cận dùng fuzzing để khám phá không gian trạng thái và phát hiện bug

Về parsing, interpreter, JIT và cấu trúc trừu tượng

  • Regular Expression Matching: the Virtual Machine Approach của Russ Cox trình bày cách triển khai regex engine chỉ với khoảng 50 dòng mã dễ đọc
    • Trong quá trình đó, bài viết cũng giải thích rất dễ hiểu các nguyên lý như coroutine, fiber và scheduler
  • micrograd của Andrej Karpathy là một ví dụ triển khai cực nhỏ giúp mạng nơ-ron hoạt động mà không cần thư viện ngoài, rất hữu ích để nắm cấu trúc và nguyên lý cơ bản của machine learning
  • How I implement SSA form của Fil Pizlo giới thiệu một cách mới để cải tiến cấu trúc union-find
    • Trong chuyển đổi SSA, con trỏ bổ sung được quản lý bằng Identity tag bên trong đối tượng
    • Ngoài ra còn gợi mở thêm nhiều điều để suy nghĩ như Phi/Upsilon form hay heap effect kiểu TBAA
    Quảng cáo
  • Speculation in JavaScriptCore của Fil Pizlo đi sâu vào nhiều cách triển khai optimizer trong JavaScriptCore
    • Mỗi lần đọc lại bài này đều có thể rút ra thêm insight mới

Về thiết kế trình biên dịch, parser, cấu trúc IR và E-Graphs

  • Trong bài nói Modernizing Compiler Design for Carbon Toolchain của Chandler Carruth (khoảng phút 29), tác giả giải thích việc đặt ra mục tiêu thời gian biên dịch cực nhanh và quá trình thiết kế toàn bộ cấu trúc
    • Từ khoảng phút 40, bài nói bắt đầu tách từng tầng để giải thích cấu trúc chi tiết hơn
  • A Python Interpreter Written in Python của Allison Kaptur giúp người đọc dễ hiểu nguyên lý hoạt động của bytecode interpreter bên trong CPython
  • Parsing expressions by precedence climbing của Eli Bendersky giới thiệu phương pháp Precedence Climbing dễ hiểu hơn parser đệ quy giảm truyền thống và cũng nhẹ gánh hơn khi phát triển
  • Ruby JIT Challenge của Takashi Kokubun cho thấy quá trình sinh mã và một cách phân bổ thanh ghi mới (stack folding at compile-time)
  • [An Incremental Approach to Compiler Construction (PDF)(https://bernsteinbear.com/assets/img/11-ghuloum.pdf) của Abdulaziz Ghuloum giải thích cách triển khai một lượt duy nhất cho phép hiểu toàn bộ thiết kế trình biên dịch nhiều giai đoạn hiện có chỉ trong một lần
    • Tác giả chọn cách bổ sung từng tính năng theo kiểu end-to-end, từng bước một
  • Lessons from Writing a Compiler của Fernando Borretti diễn giải chiến lược triển khai trình biên dịch bằng ngôn ngữ rõ ràng và mạch lạc
  • Bài báo egg: Fast and extensible equality saturation đã thay đổi tận gốc cách nhìn về optimizer và thứ tự chạy các pass
    • Bài viết đưa ra lối tư duy tạo ra một hypergraph nén chứa mọi phiên bản có thể có của biểu thức rồi chọn ra phiên bản tối ưu nhất
    Quảng cáo
  • Cranelift: Using E-Graphs for Verified, Cooperating Middle-End Optimizations của Chris Fallin chứng minh rằng e-graphs cũng vận hành hiệu quả trong các trình biên dịch thương mại thực tế
  • Acyclic Egraphs and Smart Constructors của Phil Zucker khám phá cấu trúc e-graph không chu trình và việc sử dụng smart constructor
    • Đây là bài viết lúc đầu khá khó hiểu, nhưng càng về sau càng giúp đào sâu nhận thức

Các chủ đề khác như lưu AST, phân tích động song song quy mô lớn

  • bình luận Reddit này của Bob Nystrom và Flattening ASTs của Adrian Sampson
    • nói về cách lưu AST gần như gọn như bytecode,
    • và mở ra một thảo luận lớn rằng nếu lưu IR node theo cách này thì cũng có thể phân tích quy mô lớn theo kiểu song song, lock-free
    • Nhận xét của Cliff Click về tốc độ cấp phát buffer cũng đã ảnh hưởng đến lối suy nghĩ này

1 bình luận

 
GN⁺ 2025-05-15
Ý kiến trên Hacker News
  • Tôi thực sự rất thích bài này; gần đây tôi đã đọc khá nhiều nghiên cứu khoa học máy tính, nhưng trong số những thứ được nhắc ở đây vẫn có vài thứ tôi chưa từng tiếp cận. Tôi muốn giới thiệu thêm vài bài báo mà tôi thích nhưng không có trong danh sách này: Ian Piumarta với “Open, Extensible Object Models” bàn về một hệ thống metaobject hướng đối tượng tối giản nhưng trao cho lập trình viên mức tự do tối đa; về cơ bản nó chỉ định nghĩa phép gửi thông điệp, còn mọi thứ khác đều có thể thay đổi ở runtime. Nó giống như một phiên bản thực dụng của “Art of the Metaobject Protocol”. John Ousterhout với “Scripting: Higher-Level Programming for the 21st Century” bàn về sự phân đôi giữa ngôn ngữ lập trình hệ thống và ngôn ngữ scripting. Ta luôn mong có một ngôn ngữ đa mô thức hoàn hảo vừa nhanh vừa năng suất cho mọi thứ, nhưng nhiều khi sẽ tốt hơn nếu kết hợp một ngôn ngữ hệ thống biên dịch, nhanh và phức tạp với một frontend thông dịch tiện lợi và linh hoạt. Thực ra nhiều lúc chỉ cần dùng C cùng với Tcl là đủ. Đây là bài mà bất kỳ ai làm ngôn ngữ lập trình cũng nên đọc. Project Oberon của Niklaus Wirth là một ví dụ về việc hiện thực cả một hệ thống máy tính hoàn chỉnh, từ UI cấp cao tới kernel, compiler, cho đến kiến trúc CPU kiểu RISC. Ông đã đưa ra một lời kêu gọi mạnh mẽ cho “lean software” và thực sự làm được điều đó; trong thời đại ngày nay đầy rẫy dependency hell và sự trừu tượng hóa quá mức, đó là một tay nghề thủ công đã bị đánh mất

    • Tôi không đồng ý với sự phân đôi và kết luận của Ousterhout. Luận điểm của ông ấy là ngôn ngữ либо là ngôn ngữ hệ thống (C), либо là ngôn ngữ script (Tcl, Python). Ông cho rằng ngôn ngữ hệ thống thì kiểu mạnh, dùng cho cấu trúc dữ liệu/thuật toán, còn ngôn ngữ script thì không có kiểu nên dùng để “dán nối”. Ông cũng cho rằng nhờ “không có kiểu” mà ngôn ngữ script ngắn gọn hơn và phát triển nhanh hơn, nhưng tôi nghĩ đây không phải là mô tả thực tế. Ví dụ ông so sánh mã Tcl với mã C++/MFC và nói Tcl tốt hơn, nhưng thực ra đó chỉ là vì ông thích cú pháp hơn mà thôi. Khẳng định rằng ngôn ngữ không có kiểu sẽ nhanh hơn là không đúng; chỉ là khác nhau ở chỗ bạn gặp giới hạn khi nào. Tốt hơn là kiểm tra mọi lỗi kiểu trước khi chạy, và ngôn ngữ nào cũng có thể có phân tích kiểu tĩnh, chỉ là điều đó phức tạp và khó hơn. Với tư cách là người thiết kế PL, việc chỉ kiểm tra kiểu ở runtime là một quyết định hợp lý để làm ngôn ngữ dễ xây hơn, nhưng không có nghĩa đó là lựa chọn tốt hơn
  • Tôi thực sự rất thích bài này; những bài viết về ngôn ngữ lập trình đã thay đổi cách tôi nhìn cả việc lập trình. Tôi thường nhớ đến câu trích về “tính an toàn” trong TAPL(Types and Programming Languages): một ngôn ngữ an toàn là ngôn ngữ ngăn lập trình viên tự bắn vào chân mình và bảo vệ các lớp trừu tượng của chính họ. Nói cách khác, điều quan trọng là khả năng đảm bảo tính toàn vẹn của các lớp trừu tượng mà ngôn ngữ cung cấp cũng như các lớp trừu tượng cấp cao hơn do lập trình viên tạo ra. Ví dụ, nếu có một lớp trừu tượng là mảng, thì nó chỉ nên thay đổi khi được cập nhật một cách tường minh, và không được vô tình làm hỏng các cấu trúc dữ liệu khác

  • Nói về các thói quen phát triển thú vị… Aaron Hsu, người nổi tiếng với APL, khi sắp xếp suy nghĩ thì viết mã theo kiểu thư pháp bằng bút máy. Tôi cũng làm điều gì đó tương tự: tôi dùng bút bi rẻ tiền để vẽ mấy thứ như lưu đồ của các đối tượng Python khi suy nghĩ, kiểu như một phiên bản UML giá rẻ

    • Tôi cũng thường tìm đến bút máy khi xử lý những vấn đề khó nhất. Dùng bút máy mang lại cảm giác như bước vào một không gian tư duy hoàn toàn khác. Vì khả năng chỉnh sửa bị hạn chế nên nó thúc đẩy lối suy nghĩ nhất quán và tuyến tính hơn, nhưng đồng thời lại mở ra sự sáng tạo vì tôi có thể tự do qua lại giữa tiếng Anh, code, toán học và sơ đồ

    • Đã có bằng chứng thực sự cho thấy chữ viết tay có liên hệ với việc cải thiện trí nhớ. Gõ ghi chú trên máy tính gần như chỉ như để lại dấu vân tay trên tay nắm cửa. Tôi mong công nghệ OCR sẽ tốt đến mức ta có thể ghi chép hoàn toàn bằng chữ viết tay mà vẫn lưu trữ và tìm kiếm hoàn hảo được

  • Tôi rất muốn đề xuất mọi người xem các bài nói chuyện của Rich Hickey, đặc biệt là những bài đầu tiên. Chính tôi cũng đã xem những bài đó và góc nhìn của tôi về bản thân việc lập trình đã thay đổi hoàn toàn

    • Với tôi, cùng với “Programming Perl” của Larry Wall, các bài nói chuyện của Rich Hickey là những thứ có ảnh hưởng lớn nhất

    • Tôi còn muốn đùa rằng hãy bỏ qua bài nói chuyện “Simple made easy” vì trong 10 năm qua mọi diễn giả hội nghị đều trích dẫn nó đến mức giờ đã thành sáo mòn rồi. Cá nhân tôi thấy “Hammock driven development” hay hơn, nhưng lại chưa đủ phù hợp để khuyến nghị ở công ty

  • Thật tiếc là Abdulaziz trở nên im ắng sau khi quay về Kuwait. Ông ấy từng là thực tập sinh Maxine VM năm 2009 và là một người thực sự rất tốt. Bài báo đó đúng là một viên ngọc quý

    • Tôi cũng thấy tiếc, nhưng có vẻ gần đây anh ấy đã mở một tiệm bánh và việc kinh doanh đang tiến triển tốt. Xét ở khía cạnh đó thì anh ấy đang sống đúng với giấc mơ của mình
  • Gần đây có một bài hay về interpreter dựa trên closure để tăng tốc interpreter. Tôi đã dùng kỹ thuật đó để thử làm một brainfuck interpreter đơn giản và nó khá nhanh. Có lẽ tôi sẽ không dùng nó ở nơi khác, nhưng làm như một thử nghiệm thì rất bổ ích

    • Tôi tò mò về sự khác biệt giữa một mảng closure và một mảng xen kẽ giữa function pointer với dữ liệu. Cách sau khá không tự nhiên trong hầu hết ngôn ngữ và chỉ thực sự hợp với những ngôn ngữ như C. Tuy nhiên, tôi nghĩ nếu để các hàm tĩnh và dữ liệu cùng trong mảng thì có thể sẽ thân thiện với cache hơn
  • Tôi ước cũng có những bài như thế này về các ngôn ngữ cấp cao hơn như JavaScript hay .NET. Tác giả này rõ ràng rất thông minh, nhưng ông ấy hoạt động ở tầng thấp hơn (hay cao hơn?) nhiều so với đa số người dùng

  • Những bài khác trên blog của ông ấy cũng thực sự xuất sắc

  • Về micrograd: tôi thắc mắc ngoài mã nguồn trong kho Github ra thì có thêm tài liệu nào khác không

  • Tôi nói điều này vì quý mến tác giả, nhưng các bài viết ở đây thực ra không nói về bản thân PL (ngôn ngữ lập trình), mà hầu như đều nói về compiler cả (trừ garbage collector). Tất nhiên tôi cũng thích compiler, nhưng đó là chủ đề khác với PL

    • Có lẽ ý là ngôn ngữ lập trình theo nghĩa hiện thực hóa/ch triển khai chăng?