2012-05-29 32 views
8

Ấ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?

+1

Tôi tin rằng đó chỉ là GC làm cho các trình mô tả tệp bị đóng. –

+0

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. –

+1

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. –

Trả lời

8

Tốt hơn là tự đóng tài nguyên một cách rõ ràng, chỉ khi bạn có một số ràng buộc tài nguyên cấp thấp mà bạn thực sự có thể thực thi theo cách thủ công.

Những trường hợp cần cân nhắc:

  • nguồn lực mua lại qua lười biếng IO: phải sử dụng GC để giải phóng tài nguyên
  • nghiêm ngặt IO: có thể đóng bằng tay lần đầu vào được đọc; hoặc sử dụng bộ kết hợp giá đỡ (ví dụ: finally hoặc bracket)
  • IO gia tăng (ống dẫn, lặp lại): để khuôn khổ đóng nó cho bạn.
7

Các Haddock docs for System.IO có điều này để nói:

GHC lưu ý: Xử lý sẽ tự động đóng lại khi thu gom rác phát hiện rằng nó đã trở thành unreferenced bởi chương trình. Tuy nhiên, dựa vào hành vi này thường không được khuyến nghị: người thu gom rác là không thể đoán trước. Nếu có thể, hãy sử dụng một hClose rõ ràng để đóng Handles khi chúng không còn cần thiết nữa. GHC hiện không cố gắng giải phóng các bộ mô tả tệp khi chúng đã hết, bạn có trách nhiệm đảm bảo rằng điều này không xảy ra.

Các vấn đề liên quan