Tôi đang làm việc trên trình nền Haskell để nhận và xử lý các yêu cầu JSON. Trong khi các hoạt động của daemon phức tạp, cấu trúc chính được cố tình giữ đơn giản: trạng thái bên trong của nó chỉ là một cấu trúc dữ liệu và tất cả các luồng thực hiện các hoạt động nguyên tử trên IORef
này. Sau đó, có một vài chủ đề mà trên một kích hoạt có giá trị làm một cái gì đó với nó.Gỡ lỗi rò rỉ bộ nhớ không hiển thị trên hồ sơ heap
Vấn đề là daemon đang rò rỉ bộ nhớ và tôi không thể tìm ra lý do. Nó chắc chắn liên quan đến các yêu cầu: khi daemon nhận được một số yêu cầu mỗi giây, nó rò rỉ một cái gì đó như 1MB/s (theo báo cáo của các công cụ Linux). Tiêu thụ bộ nhớ tăng đều đặn. Không có yêu cầu, mức tiêu thụ bộ nhớ vẫn không thay đổi.
Điều gì khiến tôi khó hiểu rằng không điều nào trong số này hiển thị trong hồ sơ GHC. Hoặc là tôi đang thiếu một cái gì đó trong các thông số profiling, hoặc bộ nhớ được tiêu thụ bởi cái gì khác:
Run với +RTS -hc -xt -p
:
Run với +RTS -hr -xt -p
:
Trong quá trình chạy thử nghiệm này, daemon sau đó tiêu thụ trên 1GB. Vì vậy, dữ liệu lược tả rõ ràng không tương ứng với bộ nhớ tiêu thụ thực tế theo thứ tự độ lớn. (Tôi hiểu rằng RTS, GC và bản thân lược tả thêm vào mức tiêu thụ bộ nhớ thực, nhưng sự khác biệt này quá lớn và không tương ứng với mức tiêu thụ ngày càng tăng.)
Tôi đã cố gắng rnf
tất cả dữ liệu trạng thái của daemon bên trong IORef
, cũng như các yêu cầu JSON được phân tích cú pháp (để tránh các phần của chuỗi JSON được giữ lại ở đâu đó), nhưng không thành công nhiều.
Bất kỳ ý tưởng hoặc đề xuất nào được hoan nghênh.
Cập nhật: Daemon đang chạy mà không cần -threaded
, vì vậy không có chủ đề cấp hệ điều hành.
Số liệu thống kê GC là gần gũi hơn với các hồ sơ đống hơn là những con số báo cáo của Linux:
Alloc Copied Live GC GC TOT TOT Page Flts
bytes bytes bytes user elap user elap
[...]
5476616 44504 2505736 0.00 0.00 23.21 410.03 0 0 (Gen: 0)
35499296 41624 2603032 0.00 0.00 23.26 410.25 0 0 (Gen: 0)
51841800 46848 2701592 0.00 0.00 23.32 410.49 0 0 (Gen: 0)
31259144 36416 2612088 0.00 0.00 23.40 410.61 0 0 (Gen: 0)
53433632 51976 2742664 0.00 0.00 23.49 412.05 0 0 (Gen: 0)
48142768 50928 2784744 0.00 0.00 23.54 412.49 0 0 (Gen: 0)
[...]
Cập nhật 2: Tôi tìm thấy nguồn gốc của vấn đề, rò rỉ bộ nhớ là do bởi handleToFd
(xem this issue cho thư viện unix). Tôi chỉ tự hỏi làm thế nào nó có thể xác định hiệu quả hơn một rò rỉ như vậy (có lẽ xảy ra trong một đoạn nước ngoài của mã).
Tôi sẽ đoán bộ nhớ bị rò rỉ nằm trong các byte được phân bổ bên ngoài vùng GHC. Hồ sơ heap chỉ hiển thị những gì GHC biết về, sau khi tất cả. – Carl
@Carl Và có cách nào để nắm được cách phân bổ 'ByteString' không? –
Không có gì tôi biết, ngoài việc hiểu những gì đang xảy ra trong giao diện FFI của bạn. Hãy nghi ngờ bất kỳ thư viện nào bạn đang sử dụng để thực hiện kết nối mạng. – Carl