2009-03-02 43 views
5

Tôi phải tuần tự hóa một cây khổng lồ của các đối tượng (7.000) vào đĩa. Ban đầu chúng tôi giữ cây này trong một cơ sở dữ liệu với Kodo, nhưng nó sẽ làm cho hàng ngàn khi hàng ngàn truy vấn để tải cây này vào bộ nhớ, và nó sẽ chiếm một phần tốt của vũ trụ địa phương có sẵn thời gian.Java Object Serialization Lời khuyên hiệu suất

Tôi đã cố gắng tuần tự hóa cho điều này và thực sự tôi nhận được cải thiện hiệu suất. Tuy nhiên, tôi có cảm giác rằng tôi có thể cải thiện điều này bằng cách viết mã tuần tự tùy chỉnh của riêng tôi. Tôi cần phải tải đối tượng được tuần tự hóa này càng nhanh càng tốt.

Trong máy của tôi, tuần tự hóa/deserializing các đối tượng này mất khoảng 15 giây. Khi tải chúng từ cơ sở dữ liệu, nó mất khoảng 40 giây.

Bất kỳ lời khuyên nào về những gì tôi có thể làm để cải thiện hiệu suất này, có tính đến vì các đối tượng nằm trong một cây, chúng tham chiếu lẫn nhau?

Trả lời

6

Một tối ưu hóa là tùy chỉnh bộ mô tả lớp, để bạn lưu trữ bộ mô tả lớp trong cơ sở dữ liệu khác và trong luồng đối tượng, bạn chỉ tham chiếu đến chúng bằng ID. Điều này làm giảm không gian cần thiết bởi dữ liệu tuần tự hóa. Xem ví dụ như thế nào trong một dự án các lớp học SerialUtilClassesTable làm điều đó.

Tạo các lớp Có thể thay thế được bằng Serializable có thể cung cấp một số lợi ích hiệu suất. Nhược điểm là nó đòi hỏi rất nhiều công việc thủ công.

Sau đó, có các thư viện tuần tự hóa khác, ví dụ: jserial, có thể mang lại hiệu suất tốt hơn so với tuần tự mặc định của Java.Ngoài ra, nếu đồ thị đối tượng không bao gồm chu kỳ, sau đó nó có thể được nối tiếp một chút nhanh hơn, bởi vì serializer không cần phải theo dõi các đối tượng nó đã thấy (xem "Làm thế nào nó hoạt động?" Trong jserial's FAQ).

+1

Tôi đã thực hiện các tuyến đường Externalizable trong quá khứ, và tôi đã đạt được khoảng 20-23% tăng hiệu suất trong serialization/deserialization của đồ thị đối tượng lớn. Số lượng công việc cần thiết cho điều này sẽ được tỷ lệ thuận với số lượng các đối tượng bạn phải tùy chỉnh. – Robin

+0

Chỉ cần thanh toán http://code.google.com/p/fast-serialization/. Vấn đề được giải quyết :-) –

1

Bạn đã thử nén luồng (GZIPOutputStream) chưa?

+0

Tôi cần cải thiện hiệu suất khi tải và lưu trữ, nhưng tôi không chỉ rõ trong câu hỏi và thực sự không gian cũng là một thước đo "hiệu suất". –

+0

Ít không gian hơn nghĩa là ít quyền truy cập đĩa hơn đồng nghĩa với việc ít thời gian hơn –

+0

chỉ khi quá trình tuần tự hóa bị ràng buộc đĩa.nó dường như không có trên hệ thống của tôi; nó có vẻ là cpu-ràng buộc, do đó, nén sẽ chỉ làm chậm nó xuống hơn nữa. –

1

Đây là cách tôi sẽ làm điều đó, hình thành đỉnh đầu của tôi

serialization

  1. Serialize từng đối tượng riêng
  2. Gán từng đối tượng độc đáo chính
  3. Khi một đối tượng tốt nghiệp tham chiếu đến đối tượng khác, đặt khóa duy nhất cho đối tượng đó vào vị trí đối tượng trong tuần tự hóa. (Tôi sẽ sử dụng một UUID chuyển đổi sang nhị phân)
  4. Lưu từng đối tượng vào một tập tin/cơ sở dữ liệu/lưu trữ bằng cách sử dụng độc đáo chính

Unserialization

  1. Bắt đầu tạo thành một đối tượng tùy ý (thường là thư mục gốc i nghi ngờ) unserialize nó và đặt nó trong một bản đồ với nó là khóa duy nhất như chỉ số và trả lại nó
  2. Khi bạn bước vào một khóa đối tượng trong dòng serialization, đầu tiên kiểm tra xem nó đã unserialized bằng cách tra cứu nó độc đáo quan trọng trong bản đồ và nếu nó chỉ là lấy nó từ đó, nếu không đặt một proxy tải lười (lặp lại hai bước cho đối tượng đó) thay vì đối tượng thực sự có móc để tải đúng đối tượng khi bạn cần nó.

Sửa, bạn có thể cần phải sử dụng hai-pass serialization và unserialization nếu bạn có tham chiếu vòng tròn trong đó, nó làm phức tạp mọi thứ một chút - nhưng không phải là nhiều.

+0

Điều đó có thể hoạt động, nhưng sẽ yêu cầu làm lại khá một số mã tôi có –

+0

Làm thế nào mà có thể là một cải tiến so với chuẩn hóa tuần tự? Theo như tôi biết đã được thực hiện bởi cơ chế mặc định. –

+0

@saua vì bạn có thể lười biếng tải và khởi tạo từng đối tượng khi cần thay vì tải tất cả cùng một lúc, bạn cũng có thể tự đi xuống mức byte và tối ưu hóa định dạng tuần tự hóa. – thr

0

Để có hiệu suất, tôi khuyên bạn không nên sử dụng serialization java.io. Thay vào đó hãy tự mình truy cập vào các byte.

Nếu bạn định chuyển java.io thành cây bạn có thể cần phải đảm bảo đệ quy của bạn không quá sâu, hoặc bằng cách làm phẳng (như là TreeSet) hoặc sắp xếp để nối tiếp các nút sâu nhất trước tiên (để bạn có tham chiếu ngược thay vì lồng nhau readObject cuộc gọi).

Tôi sẽ ngạc nhiên nếu không có cách nào trong Kodo đọc toàn bộ cây trong một (hoặc một vài).

+0

Có một cách trong Kodo để làm điều này, nhưng vấn đề là nó phụ thuộc vào cách các đối tượng được tạo ra trong cơ sở dữ liệu. Thật không may cơ sở dữ liệu là theo cách mà chúng tôi không thể làm điều đó (và không có cách nào để thay đổi mô hình) –

10

Đừng quên sử dụng từ khóa 'tạm thời' cho các biến mẫu không cần phải được tuần tự hóa. Điều này giúp bạn tăng hiệu suất vì bạn không còn đọc/ghi dữ liệu không cần thiết nữa.

+0

Đó là xem xét tốt, quan trọng chung trong mọi trường hợp. Tôi đã làm điều này nhưng điều quan trọng là phải đề cập đến nó. +1 –

4

Tôi khuyên bạn nên triển khai các phương thức tùy chỉnh writeObject()readObject(). Bằng cách này, bạn sẽ có thể loại bỏ các nút thất bại ghi cho mỗi nút trong một cây. Khi bạn sử dụng serialization mặc định, mỗi nút sẽ được serialized với tất cả các con của nó.

Ví dụ, writeObject() của một Tree lớp nên lặp qua tất cả các nút của cây và chỉ ghi dữ liệu các nút (không có nút riêng của mình) với một số cột mốc, trong đó xác định mức độ cây.

Bạn có thể xem LinkedList, để xem cách các phương pháp này được triển khai ở đó. Nó sử dụng cách tiếp cận tương tự để ngăn chặn việc ghi trước và các mục tiếp theo cho mỗi mục nhập.

4

Để tránh phải viết mã tuần tự hóa của riêng bạn, hãy thử dùng thử Google Protocol Buffers. Theo trang web của họ:

Bộ đệm giao thức là cơ chế mã hóa trung lập, nền tảng trung lập, có thể mở rộng của XML, nhưng nhỏ hơn, nhanh hơn và đơn giản hơn. Bạn xác định cách bạn muốn dữ liệu của mình được cấu trúc một lần, bạn có thể sử dụng mã nguồn được tạo đặc biệt để dễ dàng ghi và đọc dữ liệu có cấu trúc của bạn đến và từ nhiều luồng dữ liệu và sử dụng nhiều ngôn ngữ - Java, C++ hoặc Python

Tôi đã không sử dụng nó, nhưng đã nghe rất nhiều điều tích cực về nó. Thêm vào đó, tôi phải duy trì một số mã serialization tùy chỉnh, và nó có thể là một cơn ác mộng tuyệt đối để làm (hãy để một mình theo dõi lỗi), vì vậy hãy nhờ người khác làm điều đó cho bạn luôn là một điều tốt.

0

Ngoài ra, hãy xem XStream, một thư viện để tuần tự hóa các đối tượng thành XML và ngược lại.

+0

Tôi đã thử nó rồi, đối với những loại vật thể này thậm chí còn tệ hơn cả Kodo. Java serialization nhanh hơn XStream cho đến nay. –

0

Bạn có thể sử dụng Colfer để tạo hạt và hiệu suất tuần tự tiêu chuẩn của Java sẽ nhận được tăng 10 - 1000x. Trừ khi kích thước đạt trên một cơ hội GB bạn sẽ được dưới một giây.

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