2013-02-26 36 views
9

Tôi có một công việc đang chạy trên sản xuất xử lý các tệp xml. tệp xml có kích thước khoảng 4k và kích thước từ 8 đến 9 GB tất cả cùng nhau.Errno :: ENOMEM: Không thể cấp phát bộ nhớ - cat

Sau khi xử lý, chúng tôi nhận tệp CSV dưới dạng đầu ra. Tôi đã một lệnh mèo này sẽ hợp nhất tất cả các file CSV vào một tập tin duy nhất tôi nhận được:

Errno :: ENOMEM: Không thể cấp phát bộ nhớ

trên cat (backtick) lệnh.

Dưới đây là vài chi tiết:

  • Hệ thống Memory - 4 GB
  • Swap - 2 GB
  • Ruby: 1.9.3p286

tập tin được xử lý bằng nokogirisaxbuilder-0.0.8.

Ở đây, có một khối mã sẽ xử lý 4.000 tệp XML và đầu ra được lưu trong CSV (1 trên xml) (xin lỗi, tôi không giả sử chia sẻ nó b'coz về chính sách của công ty).

Dưới đây là đoạn code này sẽ hợp nhất các tập tin đầu ra vào một tập tin duy nhất

Dir["#{processing_directory}/*.csv"].sort_by {|file| [file.count("/"), file]}.each {|file| 
      `cat #{file} >> #{final_output_file}` 
} 

Tôi đã lấy ảnh chụp nhanh tiêu thụ bộ nhớ trong processing.It tiêu thụ hầu hết các phần của bộ nhớ, nhưng nó sẽ không Thất bại. Luôn thất bại theo lệnh cat.

Tôi đoán, khi quay lại, nó cố gắng chia rẽ một quy trình mới không có đủ bộ nhớ để không thành công.

Hãy cho tôi biết ý kiến ​​của bạn và thay thế cho điều này.

+0

IMO có ý nghĩa khi thực sự hiển thị những gì bạn đang làm. –

+0

@DaveNewton Tôi đã chỉnh sửa bài đăng của mình, cảm ơn câu trả lời của bạn – Atith

+0

Bạn có thể có rất ít bộ nhớ để điều này xảy ra, bạn có chắc là bạn còn đủ bộ nhớ không? Đầu ra của '' free -m'' là gì? – Intrepidd

Trả lời

2

Vì vậy, có vẻ như hệ thống của bạn đang chạy khá thấp trên bộ nhớ và sinh ra một vỏ + gọi mèo là quá nhiều cho bộ nhớ còn lại.

Nếu bạn không nhớ mất một số tốc độ, bạn có thể hợp nhất các tệp trong ruby, với bộ đệm nhỏ. Điều này tránh sinh sản vỏ, và bạn có thể kiểm soát kích thước bộ đệm.

này chưa được kiểm chứng nhưng bạn sẽ có được ý tưởng:

buffer_size = 4096 
output_file = File.open(final_output_file, 'w') 

Dir["#{processing_directory}/*.csv"].sort_by {|file| [file.count("/"), file]}.each do |file| 
    f = File.open(file) 
    while buffer = f.read(buffer_size) 
    output_file.write(buffer) 
    end 
    f.close 
end 
+0

Vâng, điều này có thể hiệu quả, tôi sẽ thử điều này và cho bạn biết. Và, bạn có biết bất kỳ vấn đề nào của Nokogiri trên Ruby 1.9.3 liên quan đến bộ nhớ không ?. Gần đây chúng tôi đã nâng cấp ruby ​​từ 1.9.2 lên 1.9.3, tôi cảm thấy rằng đây cũng có thể là một lý do. – Atith

2

Tôi có cùng một vấn đề, nhưng thay vì cat nó là sendmail (gem mail).

Tôi đã tìm thấy sự cố & giải pháp here bằng cách cài đặt posix-spawn đá quý, ví dụ:

gem install posix-spawn 

và đây là ví dụ:

a = (1..500_000_000).to_a 

require 'posix/spawn' 
POSIX::Spawn::spawn('ls') 

Lần này tạo tiến trình con nên thành công.

Xem thêm: Minimizing Memory Usage for Creating Application Subprocesses tại Oracle.

2

Có thể bạn đã hết bộ nhớ vật lý, vì vậy hãy kiểm tra kỹ và kiểm tra lại sự hoán đổi của bạn (free -m). Trong trường hợp bạn không có không gian hoán đổi, create one.

Nếu không, nếu bộ nhớ của bạn tốt, lỗi rất có thể do giới hạn tài nguyên của trình bao. Bạn có thể kiểm tra chúng bằng ulimit -a.

Chúng có thể được thay đổi bởi ulimit có thể sửa đổi giới hạn tài nguyên vỏ (xem: help ulimit), ví dụ:

ulimit -Sn unlimited && ulimit -Sl unlimited 

Để làm cho các giới hạn dai dẳng, bạn có thể cấu hình nó bằng cách tạo ra các tập tin ulimit thiết lập bởi các lệnh shell sau:

cat | sudo tee /etc/security/limits.d/01-${USER}.conf <<EOF 
${USER} soft core unlimited 
${USER} soft fsize unlimited 
${USER} soft nofile 4096 
${USER} soft nproc 30654 
EOF 

Hoặc sử dụng /etc/sysctl.conf để thay đổi giới hạn trên toàn cầu (man sysctl.conf) , ví dụ

kern.maxprocperuid=1000 
kern.maxproc=2000 
kern.maxfilesperproc=20000 
kern.maxfiles=50000 
Các vấn đề liên quan