2013-04-16 21 views
6

Tôi đang thực hiện truy cập tập tin rất nhanh chóng trong ruby ​​(2.0.0 p39474), và tiếp tục nhận được ngoại lệ Too many open filescủa Ruby xử lý tập tin quản lý (quá nhiều tập tin mở)

Sau khi nhìn this thread, here, và các nguồn khác nhau , Tôi biết rõ về các giới hạn của hệ điều hành (được đặt thành 1024 trên hệ thống của tôi).

Phần mã của tôi mà thực hiện tập tin này truy cập được mutexed, và có dạng:

File.open(filename, 'w'){|f| Marshal.dump(value, f) } 

nơi filename là tùy thuộc vào sự thay đổi nhanh chóng, tùy thuộc vào các chủ đề kêu gọi phần này. Đó là sự hiểu biết của tôi rằng hình thức này từ bỏ xử lý tập tin của nó sau khi khối.

Tôi có thể xác minh số lượng File đối tượng đang mở sử dụng ObjectSpace.each_object(File). Điều này báo cáo rằng có đến 100 cư dân trong bộ nhớ, nhưng chỉ có một là bao giờ mở, như mong đợi.

Hơn nữa, bản thân ngoại lệ được ném vào thời điểm chỉ có 10-40 File đối tượng được báo cáo bởi ObjectSpace. Hơn nữa, việc thu thập rác theo cách thủ công không cải thiện bất kỳ số đếm nào trong số này, cũng như làm chậm tập lệnh của tôi bằng cách chèn các cuộc gọi sleep.

Câu hỏi của tôi là, do đó:

  • Am tôi về cơ bản hiểu lầm về bản chất của giới hạn hệ điều hành --- nó bao trùm toàn bộ cuộc đời của một quá trình?
    • Nếu có, làm cách nào để máy chủ web tránh bị trục trặc sau khi truy cập trên ulimit -n tệp?
    • Có phải ruby ​​giữ lại các tệp xử lý bên ngoài hệ thống đối tượng hay hạt nhân chỉ đơn giản là rất chậm khi tính truy cập 'đồng thời'?

Sửa 20.130.417: strace chỉ ra rằng ruby ​​không ghi tất cả dữ liệu của mình cho các tập tin, trở về và phát hành các mutex trước khi làm như vậy. Như vậy, các tập tin xử lý stack lên cho đến khi giới hạn hệ điều hành.

Để khắc phục điều này, tôi đã sử dụng syswrite/sysread, chế độ đồng bộ và được gọi là flush trước close. Không có phương pháp nào trong số này hoạt động.

Câu hỏi của tôi do đó được sửa đổi thành: Tại sao ruby ​​không đóng các xử lý tệp của nó và làm thế nào tôi có thể buộc nó làm như vậy?

Trả lời

3

Sử dụng dtrace hoặc strace hoặc bất cứ điều gì tương đương là trên hệ thống của bạn, và tìm hiểu chính xác những gì các file đang được mở ra.

Lưu ý rằng đây có thể là ổ cắm.

Tôi đồng ý rằng mã bạn đã dán dường như không có khả năng gây ra sự cố này, ít nhất, không phải không có lỗi đồng thời khá lạ.

+0

'strace' chỉ ra rằng ruby ​​mở tệp, sau đó trả về từ hàm, giải phóng mutex trước khi dữ liệu được ghi. Trong một số trường hợp, nó thậm chí không tuôn ra, và kết thúc bằng văn bản vào đĩa khi đóng tài nguyên sau khi ngoại lệ (tức là trong khi tắt máy). –