Tôi đã làm việc trên một ứng dụng xử lý đồ họa/dữ liệu (you can see a screenshot here) sử dụng Clojure (mặc dù, đôi khi, có vẻ như tôi đang sử dụng Java nhiều hơn Clojure) và bắt đầu thử nghiệm ứng dụng của tôi với các tập dữ liệu lớn hơn. Tôi không có vấn đề với khoảng 100k điểm, nhưng khi tôi bắt đầu nhận được cao hơn, tôi chạy vào vấn đề không gian heap.Xử lý các tập dữ liệu lớn trong Java/Clojure: dữ liệu littleBig
Bây giờ, về mặt lý thuyết, khoảng một nửa GB nên đủ để giữ khoảng 70 triệu đôi. Cấp, tôi đang làm nhiều thứ mà đòi hỏi một số chi phí, và tôi có thể trong thực tế được giữ 2-3 bản sao của dữ liệu trong bộ nhớ cùng một lúc, nhưng tôi đã không được tối ưu hóa nhiều, và 500k hoặc hơn vẫn là đơn đặt hàng của độ lớn ít hơn tôi có thể tải.
Tôi hiểu rằng Java có giới hạn nhân tạo (có thể thay đổi) vào kích thước của heap, và tôi hiểu những có thể thay đổi, một phần, với các tùy chọn bạn có thể chỉ là JVM khởi động. Điều này dẫn tôi đến câu hỏi của tôi đầu tiên:
Tôi có thể thay đổi tối đa cho phép không gian đống nếu tôi đang sử dụng Swank-Clojure (thông qua Leiningen) JVM có khi khởi động?
Nếu tôi đóng gói ứng dụng này (như tôi dự định) làm Uberjar, tôi có thể đảm bảo JVM của tôi có một số không gian lưu trữ tối thiểu không?
Nhưng tôi không hài lòng với việc chỉ dựa vào đống JVM để cấp nguồn cho ứng dụng của tôi. Tôi không biết kích thước của dữ liệu mà cuối cùng tôi có thể làm việc, nhưng nó có thể đạt tới hàng triệu điểm, và có lẽ đống không thể chứa được điều đó. Vì vậy, tôi rất thú vị trong việc tìm kiếm giải pháp thay thế để chỉ xếp chồng dữ liệu trên đó. Dưới đây là một số ý tưởng tôi đã có, và các câu hỏi về họ:
nó có thể sẽ được đọc trong chỉ bộ phận của một (văn bản) tập tin lớn tại một thời điểm, vì vậy tôi có thể nhập và xử lý dữ liệu trong "khối", ví dụ:
n
dòng tại một thời điểm? Nếu vậy, làm thế nào?Có cách nào nhanh hơn để truy cập tệp tôi muốn đọc từ (có khả năng nhanh chóng, tùy thuộc vào việc triển khai), ngoài việc chỉ cần đọc từ một chút tại một thời điểm? Tôi đoán tôi đang yêu cầu ở đây cho bất kỳ lời khuyên/hack đã làm việc cho bạn trong quá khứ, nếu bạn đã làm một điều tương tự.
Tôi có thể "lấy mẫu" từ tệp không; ví dụ. chỉ đọc từng dòng
z
, giảm bớt dữ liệu của tôi một cách hiệu quả?
Ngay bây giờ tôi đã lên kế hoạch, nếu có câu trả lời cho câu hỏi trên (tôi sẽ tiếp tục tìm kiếm), dẫn đến các giải pháp tương đương, đọc từng đoạn dữ liệu một lúc, vẽ đồ thị vào dòng thời gian (see the screenshot - dòng thời gian có màu xanh lục) và cho phép người dùng tương tác chỉ với bit đó cho đến khi cô ấy nhấp vào next chunk
(hoặc thứ gì đó), sau đó tôi sẽ lưu các thay đổi được thực hiện cho một tệp và tải "dữ liệu" tiếp theo và hiển thị nó.
Hoặc, tôi sẽ hiển thị toàn bộ dòng thời gian của tất cả dữ liệu (được lấy mẫu xuống, vì vậy tôi có thể tải), nhưng chỉ cho phép truy cập vào một "đoạn" của nó tại một thời điểm trong cửa sổ chính (phần xem trên dòng thời gian màu xanh lục, như được phác thảo bởi hình chữ nhật khung nhìn trong dòng thời gian).
Hầu hết tất cả, tuy nhiên, là có một cách tốt hơn? Lưu ý rằng tôi không thể downsample dữ liệu của cửa sổ chính, vì tôi cần để có thể xử lý nó và cho phép người dùng tương tác với nó (ví dụ, nhấp vào một điểm hoặc gần một để thêm một "điểm đánh dấu" vào điểm đó: một quy tắc dọc trên điểm đó).
Tôi đánh giá cao bất kỳ thông tin chi tiết, câu trả lời, đề xuất hoặc chỉnh sửa nào! Tôi cũng sẵn sàng giải thích về câu hỏi của tôi theo bất kỳ cách nào bạn muốn.
Điều này hy vọng, ít nhất một phần, có nguồn mở; Tôi muốn một cách đơn giản để sử dụng nhưng nhanh chóng để tạo xy-lô của rất nhiều dữ liệu trong thế giới Clojure.
EDIT downsampling có thể chỉ khi vẽ đồ thị, và không phải lúc nào sau đó, tùy thuộc vào các phần được vẽ đồ thị. Tôi cần truy cập vào tất cả dữ liệu để thực hiện phân tích. (Chỉ cần dọn dẹp mà lên!) Mặc dù tôi chắc chắn nên nhìn vào downsampling, tôi không nghĩ rằng sẽ giải quyết vấn đề bộ nhớ của tôi trong ít nhất, như tất cả tôi đang làm cho đồ thị được vẽ trên một BufferedImage.
Cảm ơn bạn rất nhiều vì câu trả lời tuyệt vời: Tôi sẽ sớm thử một số gợi ý này. – Isaac
Tôi đã sử dụng java.io.RandomAccessFile và nhiều người tìm/readBytes để cung cấp cho tôi một hàm nhanh chóng trả về một "đoạn" của tệp. Vì vậy, tôi có thể yêu cầu các khối 512000 byte tại một thời điểm và chọn đoạn trước đó hoặc đoạn tiếp theo. Tôi sẽ đăng chức năng đủ sớm, nhưng cảm ơn bạn rất nhiều vì sự giúp đỡ! – Isaac
Bạn được chào đón. Để tối ưu hóa hơn nữa, tôi sẽ khuyên bạn nên hooking lên một hồ sơ (như VisualVM: https://visualvm.dev.java.net/), nó cho bạn thấy nơi mà thời gian và bộ nhớ được chi tiêu. Chúc may mắn với dự án :) –