Ấn tượng đầu tiên của tôi về readFile
là một sự cân bằng giữa sự tiện lợi của nó và khả năng nó để lại các mô tả tệp mở lâu hơn mức cần thiết, không có cách nào để đóng chúng lại. Theo một thử nghiệm tôi đã thử các chương trình sau đây (đánh giá cao thực tế), suy nghĩ nó có thể nghẹt thở bằng cách cố gắng để duy trì một ngàn mở file descriptor:Khi nào thì tốt hơn hết nên đóng các tay cầm tập tin?
main = do
mapM_ (\idx -> readIt) [1..1000]
where readIt = do
contents <- readFile "/etc/passwd"
putChar $ head contents
Nhưng nó thực sự làm một công việc khá tốt đòi lại file descriptor; số lượng không bao giờ vượt quá khoảng 70:
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 4
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 5
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 6
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 7
...
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 65
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 66
close(3) = 0
close(4) = 0
close(5) = 0
...
close(54) = 0
close(55) = 0
close(56) = 0
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 3
open("/etc/passwd", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE) = 4
Điều này xảy ra như thế nào? Chỉ là các giá trị của contents
đang nhận được GC'd và với các giá trị mô tả tệp không còn tham chiếu? Hoặc là có một số cơ chế riêng biệt để quản lý tài nguyên mô tả tập tin? Dù cơ chế là gì, nó có vẻ hoạt động khá tốt - làm thế nào bạn có thể biết khi nào tốt nhất nên sử dụng hClose
một cách rõ ràng?
Tôi tin rằng đó chỉ là GC làm cho các trình mô tả tệp bị đóng. –
Nói chung, tốt hơn nên sử dụng các cơ chế đảm bảo xử lý tài nguyên xác định (không phải bộ nhớ), trong Haskell là 'khung'. Đừng tin tưởng GC với các tập tin cho bất cứ điều gì nhiều hơn một trường hợp đơn giản. –
giá đỡ sẽ chỉ có ý nghĩa với IO nghiêm ngặt - nếu không hiệu ứng có thể bị rò rỉ thông qua dữ liệu lười. –