Sự trở lại của frame pointer
(brendangregg.com)- Khi Fedora và Ubuntu 24.04 LTS quay lại mặc định build kèm frame pointer cho các thành phần OS như libc, profiling trên Linux và Flame Graph có thể thấy stack đầy đủ hơn
- Nếu không có frame pointer, profiler có thể dừng stack walking ở các lớp thư viện như libc hoặc đi theo frame sai, khiến CPU/Off-CPU Flame Graph bị hỏng
- Thay đổi năm 2004 của gcc trên i386 là lựa chọn nhằm giành thêm một thanh ghi, nhưng khi lan sang cả x86-64, nó để lại chi phí dài hạn cho system profiler và khả năng quan sát dựa trên eBPF
- Từ kinh nghiệm áp dụng Java và libc tại Netflix, chi phí thường dưới 1%; một số báo cáo ghi nhận 1~2%, còn trong các microbenchmark đặc thù hoặc workload bất thường có thể lên tới 10%
- Dù có các lựa chọn thay thế như LBR, DWARF, eBPF stack walker, ORC, SFrames, Shadow Stacks, cách thực tế nhất để tìm cải thiện hiệu năng trong production hiện nay là bật frame pointer mặc định
Vì sao Flame Graph bị hỏng
- CPU Flame Graph nhìn bề ngoài có thể có vẻ bình thường, nhưng trên hệ thống mà libc được biên dịch không có frame pointer, một số mẫu có thể bị gom sai phía trên [unknown]
- Trong ví dụ, 15% mẫu ở bên trái nằm sai vị trí và thiếu các frame của ứng dụng
- Profiler đi qua các frame kernel, tới syscall và libc syscall wrapper, rồi thất bại khi phân giải symbol của frame tiếp theo
- Nguyên nhân là do tối ưu hóa của compiler khiến thanh ghi frame pointer được dùng để lưu dữ liệu thay vì làm mốc tham chiếu cho stack frame
- Profiler không thể biết giá trị đó chỉ là một con số, nên thử diễn giải nó như địa chỉ hàm
- Nếu giá trị không trỏ tới frame kế tiếp, stack walking sẽ dừng lại
- Nếu tình cờ trông giống một pointer hợp lệ, có thể sinh ra junk frame sai
- Nếu giá trị trỏ về chính nó, có thể tạo ra một tháp junk frame cho tới khi chạm giới hạn frame tối đa của perf
- Off-CPU Flame Graph có thể xuất hiện nhiều hàm libc read/write và mutex, nên khi thiếu frame pointer sẽ bị hỏng nặng hơn
- Nếu bản thân ứng dụng cũng được build không có frame pointer, không chỉ thư viện mà toàn bộ stack trace đều trở nên thiếu ổn định
Frame pointer cung cấp thông tin gì
- ABI x86-64 định nghĩa
%rbpcó thể được dùng làm base pointer của stack frame, tức frame pointer - Các profiler/debugger bên ngoài như Linux perf và eBPF dùng thông tin này để đi qua stack trace và trực quan hóa kết quả thành Flame Graph
- ABI x86-64 có chú thích rằng việc dùng
%rbplà tùy chọn- Nếu dùng
%rspđể đánh chỉ mục stack frame, có thể giảm hai lệnh trong prologue và epilogue - Có thể dùng
%rbpnhư một thanh ghi đa dụng bổ sung
- Nếu dùng
Việc loại bỏ năm 2004 và hệ quả 20 năm
- Năm 2004, gcc được thay đổi ở i386 backend để mặc định hành xử tương đương
-fomit-frame-pointer -ffixed-ebp - i386 chỉ có 4 thanh ghi đa dụng, nên giải phóng
%ebplàm tăng đáng kể số thanh ghi có thể dùng- Lý do thay đổi cũng bao gồm mong muốn đạt hiệu năng tốt hơn compiler
icccủa Intel - Khi đó cũng có đánh giá rằng debugger sẽ không bị hỏng vì hỗ trợ các kỹ thuật stack walking khác
- Lý do thay đổi cũng bao gồm mong muốn đạt hiệu năng tốt hơn compiler
- Thay đổi này cũng được áp dụng cho x86-64
- x86-64 có từ 12 thanh ghi trở lên, nên lợi ích từ việc có thêm một thanh ghi không lớn như trên i386
- Các system profiler ngày nay như eBPF chưa tồn tại vào thời điểm đó, và thay đổi này có thể khiến chúng bị hỏng
- Năm 2004, Eric Schrock cho rằng trên amd64, lợi ích từ việc có thanh ghi đa dụng thứ 17 không đủ lớn so với mất mát về khả năng debug
- Ông để lại nhận xét rằng nếu bắt đầu biên dịch
/usr/binkhông có frame pointer thì mọi thứ sẽ vượt khỏi tầm kiểm soát - Trên Linux, xu hướng tương tự lan rộng không chỉ ở
/usr/binmà cả/usr/libvà mã ứng dụng
- Ông để lại nhận xét rằng nếu bắt đầu biên dịch
Kinh nghiệm áp dụng với Java, libc và Netflix
- Khi gia nhập Netflix năm 2014, do Java thiếu hỗ trợ frame pointer nên toàn bộ stack ứng dụng đều bị hỏng
- Một bản sửa cho JVM c2 compiler đã được tạo, và Oracle làm lại nó rồi thêm vào JDK8u60 dưới dạng tùy chọn
-XX:+PreserveFramePointer - Thay đổi ở Java giúp tìm ra nhiều cải thiện hiệu năng trong mã ứng dụng, nhưng libc vẫn làm hỏng một phần mẫu CPU và phần lớn Off-CPU Flame Graph
- Sau đó, Netflix tự biên dịch libc có kèm frame pointer để dùng trong production, đồng thời cũng làm việc với Canonical về libc build sẵn cho Ubuntu
- Trong một thời gian, việc dùng
libc6-profđược khuyến nghị libc6-proflàlibc6có kèm frame pointer
- Trong một thời gian, việc dùng
Overhead hiệu năng và các trường hợp ngoại lệ
- Trong quá trình áp dụng production, chi phí khi thêm frame pointer vào libc và Java thường dưới 1%
- Có một ứng dụng ngoại lệ ghi nhận overhead 10%
- Đó là một ứng dụng đặc biệt tạo stack trace hơn 1000 frame thông qua Groovy
- Linux perf cũng không xử lý được trường hợp này, nên Arnaldo Carvalho de Melo của Red Hat đã thêm sysctl
kernel.perf_event_max_stackcho workload của Netflix - Môi trường đó là máy ảo không có tính năng profiling phần cứng cấp thấp, nên không thể xác nhận toàn bộ 10% có phải do frame pointer hay không
- Các báo cáo khác cũng ghi nhận chi phí khoảng 1% hoặc 2%
- Microbenchmark có thể xấu đi tới 10%
- Khi lặp lại các hàm nhỏ trong vòng lặp, các lệnh bổ sung có thể ảnh hưởng tới độ ấm của L1 cache hoặc ranh giới cache line
- Trong trường hợp này, không hẳn do bản thân frame pointer; thêm bất cứ thứ gì vào hàm hot cũng có thể gây hiệu ứng tương tự
- Benchmark Python
scimark_sparse_mat_multcũng có thể đạt tới 10%- Trong phân tích của Andrii Nakryiko, đây là một trường hợp đặc thù: với hàm lớn, gcc dùng offset tương đối theo
%rbpthay vì offset%rsp, cần nhiều byte hơn và gây vấn đề hiệu năng - Sau đó cũng có tin rằng Python đã được sửa để có thể bật lại frame pointer mặc định
- Trong phân tích của Andrii Nakryiko, đây là một trường hợp đặc thù: với hàm lớn, gcc dùng offset tương đối theo
- Những cải thiện hiệu năng tìm được nhờ frame pointer dao động từ 5% đến 500%, nên chi phí thường dưới 1% được xem là có thể biện minh
- Nếu là thiết bị không có khả năng profiling hay debugging thì có thể biên dịch không có frame pointer, nhưng đối tượng chính ở đây là enterprise Linux và backend server
Fedora và Ubuntu bật mặc định
- Các công ty lớn như Meta, Google, Netflix đã tự dùng libc có kèm frame pointer để bảo đảm khả năng profiling
- Nỗ lực đầu tiên nhằm upstream việc bật mặc định vào Fedora đã dẫn tới tranh luận kéo dài
- Thảo luận Fedora trở thành một thread với 116 bài viết
- Một người tham gia yêu cầu Meta hoặc Netflix cung cấp hạ tầng side repository để kiểm thử, benchmark và đo kích thước mã
- Jonathan Corbet đã tóm tắt việc này trong Fedora's tempest in a stack frame
- Sau đó Fedora xem xét lại và chấp nhận đề xuất, trở thành bản phân phối đầu tiên bật lại frame pointer
- Ubuntu cũng công bố frame pointers by default trong Ubuntu 24.04 LTS
- Có thêm tin rằng Arch Linux cũng đang tiến hành bật frame pointer
- Stack walking trong thư viện OS sẽ được cải thiện nhờ thay đổi này, nhưng runtime ứng dụng có thể cần cấu hình riêng
- Java cung cấp tùy chọn
-XX:+PreserveFramePointer - Go đã mặc định hỗ trợ frame pointer từ vài năm trước
- Java cung cấp tùy chọn
Các ứng viên stack walking sau frame pointer
- LBR(Last Branch Record): tính năng phần cứng của Intel, bị giới hạn 16 hoặc 32 frame nên không đủ cho phần lớn stack ứng dụng, nhưng có thể dùng như phương án cuối để lấy một phần thông tin stack
- BTS(Branch Trace Store): tính năng của Intel, ít bị giới hạn độ sâu stack hơn nhưng có chi phí cho memory load/store và xử lý BTS buffer overflow interrupt
- AET(Architectural Event Trace): tracer dựa trên JTAG, có thể trace CPU cấp thấp, BIOS và device event, và có vẻ cũng dùng được cho stack trace, nhưng chưa có kinh nghiệm sử dụng trực tiếp
- DWARF: cơ chế binary debuginfo đã được dùng lâu trong debugger
- Có ý kiến chỉ ra rằng từng có công việc JIT-to-DWARF trong các JIT runtime
- Không kỳ vọng nó thực tế với Java JVM nơi c2 chạy liên tục trên server production bận rộn
- Bản thân DWARF stack walking cũng có chi phí cao
- eBPF stack walking: tracer bên ngoài có thể đi vào bên trong runtime như JVM mà không cần hỗ trợ từ runtime
- Có thể phải đọc nhiều phần bên trong runtime bằng user space read, nên overhead có thể cao
- Vì dễ bị ảnh hưởng bởi thay đổi của runtime, phù hợp hơn khi được phát hành và duy trì cùng code base của ngôn ngữ
- ORC(oops rewind capability): stack unwinder nhẹ của Linux kernel, cho phép kernel mới vẫn duy trì stack walking dù loại bỏ frame pointer
- SFrames(Stack Frames): phương thức unwinding stack người dùng nhẹ dựa trên ORC
- Shadow Stacks: tính năng bảo mật của Intel và AMD, push địa chỉ return của hàm vào stack phần cứng riêng để kiểm chứng tại thời điểm return, và có vẻ cũng có thể tận dụng cho stack trace
Điều thay đổi ngay lúc này
- Lợi ích hiệu năng trên i386, đánh giá tương thích debugger thời đó và cạnh tranh với
icc— các lý do của việc bỏ frame pointer năm 2004 — không còn phù hợp với bối cảnh năm 2024 - Việc loại bỏ frame pointer áp dụng cho x86-64 ngay từ lúc đó đã được đánh giá là lợi ích không đủ lớn so với mất mát về khả năng debug
- Khi Fedora và Ubuntu khôi phục frame pointer, người dùng các bản phát hành năm 2024 sẽ có CPU Flame Graph dễ hiểu hơn và lần đầu có thể sử dụng đúng nghĩa Off-CPU Flame Graph
- Continuous profiler cũng dễ thu được profile đầy đủ hơn mà không cần yêu cầu khách hàng thay đổi OS
- Trong tương lai, có thể lại stack trace không cần frame pointer bằng các cách như SFrames hoặc Shadow Stacks, nhưng cải thiện khả thi hiện nay là bật frame pointer làm mặc định
1 bình luận
Các ý kiến trên Hacker News
Tôi nhớ thời điểm đầu những năm 2000, khi việc bỏ qua con trỏ khung ngăn xếp bắt đầu lan rộng
Khi đó tôi học khoa học máy tính tại một trường đại học ở một quốc gia thế giới thứ ba nghèo, và vì máy tính cũ kỹ, chậm chạp nên phần lớn bài tập dùng trình biên dịch thay vì trình thông dịch
Có nhiều môn thú vị, từ cấu trúc dữ liệu mức thấp, trình biên dịch, các routine số học bằng assembly cho tới driver thiết bị Minix; mỗi khi chương trình chạy kỳ lạ, tôi gắn gdb vào và tự lần theo stack ở mức assembly để debug
Nhưng rồi đột nhiên
-fomit-frame-pointertrở nên thịnh hành, khiến stack trace bắt đầu trở nên vô nghĩa, và việc debug segfault hay illegal instruction khó hơn nhiềuCuối cùng, để tránh các phiên debug bị hỏng, tôi bắt đầu dùng Python cho hầu như mọi việc; hiệu năng mất một đến hai bậc độ lớn, nhưng việc học Python về sau lại hữu ích
-fno-omit-frame-pointerkhôngRất vui khi Fedora được nhắc tới. Việc duy trì trạng thái bật frame pointer trên toàn bộ bản phân phối là một cuộc chiến khá mệt mỏi
Ví dụ: https://pagure.io/fesco/issue/3084
Vẫn còn một huyền thoại rằng overhead của frame pointer là lớn, xuất phát từ một trường hợp Python từng chậm hơn +10%, nhưng nay đã được sửa
Overhead đo được thực tế là dưới 1%, trong khi lợi ích thu được ở một số ứng dụng cụ thể lớn hơn nhiều
Nó cũng không khớp lắm với các phép đo phía kernel Linux, nơi tôi thấy con số nằm trong khoảng 5–10%: https://lore.kernel.org/lkml/20170602104048.jkkzssljsompjdwy...
Với nhiều workload khác nhau như netperf, microbenchmark của page allocator, pgbench, sqlite, việc bật frame pointer gây overhead 5–10%, và điểm quan trọng là tác động đã được thấy với PostgreSQL và SQLite
DBMS là một trong những cách tốt để tạo áp lực mạnh lên hệ thống
OCaml 5 dùng stack riêng cho mã OCaml và mã C; GDB có thể nối hai stack này bằng thông tin DWARF, nhưng call graph DWARF của perf thì không làm được: https://github.com/ocaml/ocaml/issues/12563#issuecomment-193...
Nếu cần lý do để tiếp tục giữ frame pointer trong các bản phát hành tương lai, có thể lấy OCaml 5 làm ví dụ
Giờ tôi mới biết Fedora 39 đã bật frame pointer theo mặc định; còn công việc profiling thường ngày của tôi vẫn chủ yếu diễn ra trên các hệ thống kiểu CentOS 7, nơi tôi vẫn dùng
perf record --call-graph dwarf -F 47 -aLý do loại bỏ frame pointer không phải là huyền thoại, mà bắt nguồn từ thực tế của thời kỳ trước 64-bit, và chuyện đó cũng chưa quá xa xưa
Ngay cả hiện nay, nếu muốn thổi sức sống mới vào các hệ thống 64-bit cũ, những tối ưu hóa như vậy vẫn có ý nghĩa
Lý tưởng là nó cũng nên là mặc định trong các hệ thống coi trọng bảo mật, và không phải mọi thứ đều cần được tối ưu cho “khả năng quan sát”
Có một điều Apple làm tốt trên ARM: họ bảo đảm frame pointer x29 luôn trỏ tới một bản ghi frame hợp lệ
Một số hàm như leaf function hoặc tail call có thể không tạo mục trong danh sách, nhưng nhờ đó, ngay cả khi không có thông tin debug, stack trace vẫn luôn còn có ý nghĩa
https://developer.apple.com/documentation/xcode/writing-arm6...
Năm 2005, tôi đứng ở phía phản đối tại Google, và suy nghĩ khi đó rất đơn giản
Ngay cả nếu
$BIG_COMPANYquyết định biên dịch mọi thứ với frame pointer, phần còn lại của cộng đồng cũng sẽ không làm vậy, nên chúng tôi sẽ tiếp tục sa vào một cuộc tranh luận không thể thắng với một cộng đồng lớn hơn nhiềuKết quả là cuộc tranh luận đó gần như đã trở thành một cuộc tranh luận kéo dài 20 năm, và về sau tôi viết các bản vá để libunwind hoạt động trong gperftools, rồi duy trì libunwind trong vài năm
Giờ tôi đã chuyển sang một lĩnh vực điện toán khác và chỉ còn là người quan sát thụ động, nhưng đọc lại lịch sử từ góc nhìn của phía đối lập thật thú vị
Nếu định truyền RBP làm frame pointer thì thà để hai stack cũng được
Một stack do RBP trỏ tới để lưu activation frame, stack còn lại do RSP trỏ tới và chỉ lưu địa chỉ trả về
Khi đó call stack đúng nghĩa là một mảng phẳng các địa chỉ trả về, nên cũng không cần phải “đi qua stack” nữa
Ngay từ đầu tôi cũng không hiểu vì sao lại lưu địa chỉ trả về gần biến cục bộ, và thấy nhược điểm quá nhiều
Cách đề xuất cần hai guard page, thao tác stack cũng tăng gấp đôi, và khả năng cache miss cũng tăng gấp đôi
Tôi biết lý do, nhưng như nhiều thứ khác, có lẽ lần cuối nó còn hợp lý là khoảng 30 năm trước, và ảnh hưởng của nó thì khá thú vị
Kỳ lạ là bài Wikipedia dường như không nhấn mạnh như một đặc trưng lớn của mô hình rằng Forth có thể truy cập cả parameter stack lẫn return stack
https://en.wikipedia.org/wiki/Forth_(programming_language)
Cần chứng minh rằng chi phí chuyển nó sang trang riêng và quản lý hai con trỏ thực sự rẻ hơn stack cookie/protector, thứ vốn chỉ cung cấp bảo vệ ở những nơi cần thiết
Nó cũng không có lợi ích bảo mật thực chất hơn stack protector hiện nay. Nếu có thể đọc/ghi tùy ý thì cuối cùng vẫn có thể dẫn đến việc vượt qua tính toàn vẹn luồng điều khiển
Virgil không dùng frame pointer. Nếu không có cấp phát stack động, kích thước frame của một hàm cụ thể là cố định và có thể tìm bằng một lần tra bảng nhị phân đơn giản
Kỹ thuật của Virgil dùng thêm phạm vi dựa trên chỉ mục trang để thu hẹp việc tra cứu xuống chỉ còn vài phép so sánh trung bình, kết hợp thông tin unwind với stackmap cho GC, và dùng rất ít không gian
Mã chính nằm ở https://github.com/titzer/virgil/blob/master/rt/native/Nativ... và phần mã còn lại trong cùng thư mục triển khai giải mã metadata
Tôi cho rằng frame pointer chỉ có ý nghĩa khi kích thước frame là động, tức là khi cấp phát dữ liệu trên stack
Dùng một cơ chế động trong khi cơ chế tĩnh đã đủ là điều kỳ lạ, và có vẻ chủ yếu là vì không có sự thống nhất về ABI mã hóa metadata hoặc routine unwind
Con số đo được 1–2% là đáng tin, và ở mức tương tự chi phí kiểm tra biên mảng
Việc dành đối xử đặc biệt cho chi phí 1% trong debugging và profiling, nhưng lại ngần ngại khi thêm lớp bảo mật, cho thấy thứ tự ưu tiên rất kỳ lạ
std::vectorcủa C++ mặc định tắt kiểm tra biên, mà theo tôi là vì C++ được thiết kế bởi những người hoàn toàn điên rồ, và cũng dành cho những người như vậyNgoài ra tôi không nghĩ ngay ra ngôn ngữ nào không có kiểm tra biên
Bài viết hay. Tôi đã thấy tiếc khi frame pointer biến mất
Không chỉ trên các hệ thống khác, mà ngay cả trên Linux, nhiều người đã khổ sở trong thời gian dài vì thiếu frame pointer, và đã cố giữ nó ở càng nhiều môi trường càng tốt
Thấy Linux chính thống đưa nó trở lại đem lại cảm giác được công nhận, nhưng đồng thời cũng hơi bực bội
Trên họ Debian thì nó chậm vì lý do giấy phép khiến perf chỉ đóng gói đường unwind chậm, nhưng nếu công cụ ổn thì gần như không cảm nhận được khác biệt
Tôi muốn biết mình đang bỏ lỡ điều gì
Nhìn chung tôi ủng hộ frame pointer, nhưng sau vài năm làm việc trong lĩnh vực này, tôi có một số cảm nhận
Nhiều cách unwind stack dựa trên frame pointer không tính đến một vấn đề mà thông tin unwind DWARF không gặp phải. Việc thiết lập frame không mang tính nguyên tử, mà gồm hai lệnh
push $rbpvàmov $rsp $rbp; nếu snapshot được chụp trong lúcpush, có thể bỏ lỡ frame chaCó thể giảm nhẹ bằng cách kiểm tra mã, nhưng cũng có thể có
push %rbpkhông liên quan đến stack frame, nên trông gần giống heuristic hơnChúng tôi cũng đã phát triển một giải pháp unwind nhanh trong kernel dựa trên BPF mà Brendan đã nhắc đến: https://web.archive.org/web/20231222054207/https://www.polar...
Cách này không dùng nguyên DWARF CFI, mà chuyển đổi nó sang một định dạng truy cập ngẫu nhiên có thể dùng trong BPF
Hiện tại chỉ hỗ trợ các section JIT có frame pointer, nhưng tôi nghĩ có thể triển khai việc unwind interpreter của JVM sao cho khớp với unwind native
Lý tưởng nhất là nên bật frame pointer theo từng trường hợp, và benchmarking là yếu tố then chốt
Tùy theo ngành và tính chất phần mềm, sự đánh đổi giữa hiệu năng, khả năng quan sát và các chỉ số kinh doanh có thể khác nhau rất lớn
Phía Fedora đã làm việc này rất xuất sắc và nghiêm ngặt
Ngoài ra, một build system có thể thay đổi thiết lập này trên toàn hệ thống, bao gồm cả các thư viện phụ thuộc, sẽ rất hữu ích không chỉ cho kiểm thử mà cả khi áp dụng vào vận hành
Cuối cùng, tôi rất kỳ vọng vào SFrame mà Indu đang làm. Nó có vẻ sẽ giải quyết được nhiều vấn đề hiện tại, đồng thời cho phép người dùng chọn có dùng frame pointer hay không, nhưng có thể sẽ mất vài năm để hạ tầng sẵn sàng và mọi người nâng cấp
Để hiểu thực sự chuyện gì đang diễn ra, cần phân tích toàn hệ thống, và với cấu trúc các bản phân phối Linux nhị phân hiện nay như Fedora hay Debian, gần như không có lựa chọn thay thế nào khác
ENTER N,0dành ra N dung lượng stack cho biến cục bộ, đại khái tương đươngPUSH EBP,MOV ESP,ESP,SUB SP,NTuy nhiên tôi không nhớ
ENTERcó trong x86-64 hay khôngDù vậy, giữa
CALLvà thiết lập frame vẫn không nguyên tử, nên nếu snapshot được chụp sauCALLnhưng trướcENTER, sẽ không lấy được thiết lập frameLý do
ENTERít được dùng là vì nó bị đánh giá là quá chậmLEAVEđược dùng vì nó nhanh bằng hoặc nhanh hơn chuỗi lệnh mà nó thay thế, nhưngENTERthì toán hạng thứ hai làm hỏng hiệu năngToán hạng đó dùng để hàm lồng nhau truy cập stack frame phía trên, và chi phí sử dụng rất lớn
Thật thú vị khi giờ mới hiểu vì sao trong profile lại xuất hiện cả một “núi”
[unknown]Tuy nhiên việc biện minh cho điều này không dễ. Chênh lệch hiệu năng 2% thực ra là khá lớn
Sẽ tốt hơn nếu có thể kiểm soát việc có đưa frame pointer vào hay không một cách tinh hơn
Nếu có profiling chi tiết, ta có thể quyết định liệu một hàm hoặc một đơn vị biên dịch cụ thể có cần frame pointer hay không
Tôi cũng sẽ không ngạc nhiên nếu kết quả cho thấy chỉ một số ít tác vụ chậm đi đáng kể khi thêm frame pointer, còn phần còn lại hầu như không bị ảnh hưởng
__attribute__((optimize("no-omit-frame-pointer")))__attribute__((optimize("omit-frame-pointer")))Những benchmark kiểu này hơi nhân tạo nên không nên tin hoàn toàn, và ứng dụng thực tế thường cho kết quả rất khác
Profiling rất quan trọng; tôi từng profile mã một cách kỹ lưỡng và làm nhiều đoạn chạy nhanh hơn tới 20%
Nếu ứng dụng cực kỳ nhạy với mất mát hiệu năng, có thể bật frame pointer và profile trong phòng thí nghiệm, rồi bỏ qua nó ở bản phát hành cho khách hàng
Hỗ trợ mã JIT đáng tiếc là chưa tốt, nhưng LLVM có hook tuyệt vời để ghi lại từng method được sinh ra cùng địa chỉ của nó
Vì vậy có thể tạo một cơ chế unwind stack chế độ hỗn hợp đơn giản tương đối dễ, nhưng chủ yếu là khả thi từ bên trong process
Dòng DNN của Intel có vẻ dump thông tin ra một file công khai mà perf có thể đọc, nhưng bản thân kernel của oneDNN cứ tái sử dụng RBP liên tục nên trên thực tế gần như vô dụng
Khẳng định trong bài rằng “các runtime JIT như Java JVM không có thông tin DWARF” cũng khiến tôi ngạc nhiên
Tôi thắc mắc liệu nó bị tắt mặc định, hay đúng nghĩa là không thể dùng được
Tìm kiếm thì thường dẫn đến nội dung muốn đưa cả phía JNI/C vào stack JVM: https://github.com/async-profiler/async-profiler/issues/215