From 314236593f875c1fc64ea9ab2c7750795840acf7 Mon Sep 17 00:00:00 2001 From: hoanthetran Date: Fri, 28 Oct 2022 09:22:05 +0700 Subject: [PATCH 1/3] add post java object serialization --- Gemfile.lock | 84 ++++--- _data/authors.yml | 9 + .../2022-10-25-java-object-serialization.md | 229 ++++++++++++++++++ assets/images/avatars/blu3.jpg | Bin 0 -> 25131 bytes .../posts/2022-10-25/serialization-1.png | Bin 0 -> 15526 bytes .../posts/2022-10-25/serialization-2.png | Bin 0 -> 21217 bytes .../posts/2022-10-25/serialization-3.png | Bin 0 -> 15276 bytes .../posts/2022-10-25/serialization-f-1.png | Bin 0 -> 28817 bytes 8 files changed, 283 insertions(+), 39 deletions(-) create mode 100644 _posts/2022-10-25-java-object-serialization.md create mode 100644 assets/images/avatars/blu3.jpg create mode 100644 assets/images/posts/2022-10-25/serialization-1.png create mode 100644 assets/images/posts/2022-10-25/serialization-2.png create mode 100644 assets/images/posts/2022-10-25/serialization-3.png create mode 100644 assets/images/posts/2022-10-25/serialization-f-1.png diff --git a/Gemfile.lock b/Gemfile.lock index b8a4ce2..88a1028 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,70 +1,76 @@ GEM remote: https://rubygems.org/ specs: - addressable (2.6.0) - public_suffix (>= 2.0.2, < 4.0) + addressable (2.8.1) + public_suffix (>= 2.0.2, < 6.0) colorator (1.1.0) - concurrent-ruby (1.1.5) - em-websocket (0.5.1) + concurrent-ruby (1.1.10) + em-websocket (0.5.3) eventmachine (>= 0.12.9) - http_parser.rb (~> 0.6.0) + http_parser.rb (~> 0) eventmachine (1.2.7) - ffi (1.10.0) + ffi (1.15.5) forwardable-extended (2.6.0) - http_parser.rb (0.6.0) - i18n (0.9.5) + http_parser.rb (0.8.0) + i18n (1.12.0) concurrent-ruby (~> 1.0) - jekyll (3.8.5) + jekyll (4.3.0) addressable (~> 2.4) colorator (~> 1.0) em-websocket (~> 0.5) - i18n (~> 0.7) - jekyll-sass-converter (~> 1.0) + i18n (~> 1.0) + jekyll-sass-converter (>= 2.0, < 4.0) jekyll-watch (~> 2.0) - kramdown (~> 1.14) + kramdown (~> 2.3, >= 2.3.1) + kramdown-parser-gfm (~> 1.0) liquid (~> 4.0) - mercenary (~> 0.3.3) + mercenary (>= 0.3.6, < 0.5) pathutil (~> 0.9) - rouge (>= 1.7, < 4) + rouge (>= 3.0, < 5.0) safe_yaml (~> 1.0) - jekyll-feed (0.12.1) + terminal-table (>= 1.8, < 4.0) + webrick (~> 1.7) + jekyll-feed (0.17.0) jekyll (>= 3.7, < 5.0) jekyll-paginate (1.1.0) - jekyll-sass-converter (1.5.2) - sass (~> 3.4) - jekyll-sitemap (1.3.1) + jekyll-sass-converter (2.2.0) + sassc (> 2.0.1, < 3.0) + jekyll-sitemap (1.4.0) jekyll (>= 3.7, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) - kramdown (1.17.0) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) liquid (4.0.3) - listen (3.1.5) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) - ruby_dep (~> 1.2) - mercenary (0.3.6) - msgpack (1.2.9) - multi_json (1.13.1) - neovim (0.8.0) + listen (3.7.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.4.0) + msgpack (1.6.0) + multi_json (1.15.0) + neovim (0.9.0) msgpack (~> 1.1) multi_json (~> 1.0) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (3.0.3) - rb-fsevent (0.10.3) - rb-inotify (0.10.0) + public_suffix (5.0.0) + rb-fsevent (0.11.2) + rb-inotify (0.10.1) ffi (~> 1.0) - rouge (3.3.0) - ruby_dep (1.5.0) + rexml (3.2.5) + rouge (4.0.0) safe_yaml (1.0.5) - sass (3.7.4) - sass-listen (~> 4.0.0) - sass-listen (4.0.0) - rb-fsevent (~> 0.9, >= 0.9.4) - rb-inotify (~> 0.9, >= 0.9.7) + sassc (2.4.0) + ffi (~> 1.9) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.3.0) + webrick (1.7.0) PLATFORMS - ruby + arm64-darwin-20 DEPENDENCIES jekyll (>= 3.6.3) @@ -76,4 +82,4 @@ DEPENDENCIES rouge BUNDLED WITH - 1.13.6 + 2.2.22 diff --git a/_data/authors.yml b/_data/authors.yml index 0867854..b88afd8 100644 --- a/_data/authors.yml +++ b/_data/authors.yml @@ -76,5 +76,14 @@ sherry: cover: /assets/images/covers/casper.jpg name: Trâm Anh location: In the shell + intro: > + I'm a ghost... + +blu3: + username: blu3 + avatar: /assets/images/avatars/blu3.jpg + cover: /assets/images/covers/casper.jpg + name: blu3 + location: In the shell intro: > I'm a ghost... \ No newline at end of file diff --git a/_posts/2022-10-25-java-object-serialization.md b/_posts/2022-10-25-java-object-serialization.md new file mode 100644 index 0000000..647b922 --- /dev/null +++ b/_posts/2022-10-25-java-object-serialization.md @@ -0,0 +1,229 @@ +--- +layout: post +cover: 'assets/images/covers/cover4.jpg' +title: Object serialization performance +date: 2022-10-25 +tags: [Java, bài dịch, serialization] +author: blu3 +description: > + Java performance - Object serialization +--- + +## Objects Serialization performance + +XML, JSON, và định dạng tương tự như text-based chúng rất hữu ích cho việc trao đổi dữ liệu giữa các hệ thống. Giữa các tiến trình trong Java, dữ liệu thường được trao đổi thông qua trạng thái tuần tự hoá của một đối tượng. Mặc dù nó được sử dụng rộng rãi trong Java, tuần tự hoá có 2 quan điểm quan trọng cần xem xét trong Java EE: +- EJB được gọi giữa các máy chủ Java EE - EJB gọi từ xa - Sử dụng tuần tự hoá để trao đổi dữ liệu +- Trạng thái phiên làm việc của giao thức HTTP được lưu thông qua tuần tự hoá đối tượng, điều này cho phép các phiên làm việc thông qua giao thức HTTP có tính khả dụng cao. + +JDK cung cấp một cơ chế mặc định để tuần tự hoá các đối tượng thông qua triển khai giao diện Serializable hoặc giao diện Externalizable. Trên thực tế, hiệu suất tuần tự hoá của mọi đối tượng có thể được cải thiện từ tuần tự hoá mặc định, nhưng chắc chắn ngay từ đầu không phải là thời điểm thích hợp để thực hiện tối ưu tuần tự hoá. Mã code đặc biệt để serialize và deserialize sẽ tốn thời gian để viết, và Mã code sẽ khó bảo trì hợn so với cơ chế mặc định. Mã code tuần tự hoá cũng có thể phức tạp, vì vậy việc cố gắng tối ưu hoá nó sẽ làm tăng nguy cơ tạo ra mã code không chính xác. + +### Transient Fields +Nói chung, cách để cải thiện chi phí tuần tự hoá đối tượng là tuần tự hoá ít dữ liệu nhất có thể. Điều này được thực hiện bằng cách đánh dấu các trường không cần thiết là tạm thời. Khi được đánh dấu tạm thời chúng sẽ không được tuần tự hoá theo mặc định. Sau đó, lớp có thể cung cấp các phương thức `writeObject()` và `readObject()` đặc biệt để xử lý dữ liệu đó. + +### Overriding Default Serialization +Phương thức `writeObject()` và `readObject()` cho phép kiểm soát hoàn toàn dữ liệu được tuần tự hoá. Với khả năng kiểm soát tốt đi kèm với trách nhiệm lớn: điều này rất dễ mắc sai lầm. + +Để biết được lý do tại sao tối ưu hoá tuần tự hoá là phức tạp, hãy lấy trường hợp của một đối tượng Point đơn giản đại diện cho vị trí: +```java +public class Point implements Serializable { + private int x; + private int y; + ... +} +``` +Trên máy tính của tôi, 100.000 đối tượng trong số này được tuần tự hoá trong 113 mili giây và được giải mã trong 741 mili giây. Nhưng ngay cả khi đối tượng đó đơn giản như vậy, nó có thể rất, rất khó để đạt được hiệu xuất được cải thiện: +```java +public class Point implements Serializable { + private transient int x; + private transient int y; + ... + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + oos.writeInt(x); + oos.writeInt(y); + } + private void readObject(ObjectInputStream ois) + throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + x = ois.readInt(); + y = ois.readInt(); + } +} +``` +Việc tuần tự hoá 100.000 đối tượng trên máy tính của tôi vẫn mất 132 mili giây, nhưng việc giải mã tuần tự chỉ mất 468 mili giây (cải thiện 30% hiệu suất). Nếu giải mã một đối tượng đơn giản là điều chiếm 1 phần đáng kể trong một chương trình, thì việc tối ưu hoá như này có thể là hợp lý. Tuy nhiên, hãy lưu ý nó làm cho mã code khó bảo trì hơn khi các trường được thêm vào, di chuyển... + +Tuy nhiên cho tới lúc này, mã code phức tạp hơn nhưng vẫn đúng về mặt chức năng (và nhanh hơn). Nhưng hãy cần thận khi sử dụng kỹ thuật này trong trường hợp chung: +```java +public class TripHistory implements Serializable { + private transient Point[] airportsVisited; + .... + // THIS CODE IS NOT FUNCTIONALLY CORRECT + private void writeObject(ObjectOutputStream oos) throws IOException { + oos.defaultWriteObject(); + oos.writeInt(airportsVisited.length); + for (int i = 0; i < airportsVisited.length; i++) { + oos.writeInt(airportsVisited[i].getX()); + oos.writeInt(airportsVisited[i].getY()); + } + } + private void readObject(ObjectInputStream ois) + throws IOException, ClassNotFoundException { + ois.defaultReadObject(); + int length = ois.readInt(); + airportsVisited = new Point[length]; + for(inti=0;i prices = new TreeMap<>(); + protected Date firstDate; + protected Date lastDate; + protected boolean needsCalc = true; + protected BigDecimal highPrice; + protected BigDecimal lowPrice; + protected BigDecimal averagePrice; + protected BigDecimal stdDev; + private Map> histogram; + .... + public StockPriceHistoryImpl(String s, Date firstDate, Date lastDate) { + prices = .... + } +} +``` +Khi lịch sử của hàng tồn kho được xây dựng trên ký hiệu `s`, đối tượng được tạo và lưu trữ trên một bản đồ giá được sắp xếp theo ngày của tất cả các giá từ đầu đến cuối. Mã code cũng lưu lại ngày đầu tiên và ngày cuối cùng. Hàm tạo không điền vào bất kỳ một trường nào khác, chúng được tạo một cách lười biếng. Khi một getter trên bất kỳ trường nào được gọi, getter sẽ kiểm tra xem `needsCalc` có đúng không. Nếu có, nó sẽ tính toán các giá trị thích hợp cho tất cả các trường còn lại nếu cần (tất cả cùng một lúc). + +Tính toán này bao gồm việc tạo biểu đồ, ghi lại số ngày hàng tồn kho đóng lại ở một mức giá cụ thể. Biểu đồ chứa đựng cùng một dữ liệu ?(về đối tường `BigDecimal` và `Date`) như được tìm thấy trong bản đồ giá; nó chỉ là một cách nhìn khác về dữ liệu. + +Bởi vì tất cả các trường được khởi tạo một cách lười biếng có thể tính toán từ mảng giá, tất cả chúng có thể được đánh dấu tạm thời, và không cần thực hiện công việc đặc biệt nào để tuần tự hoá và giải mã chúng. Ví dụ này rất dễ dàng trong trường hợp này vì mã code đã thực hiện việc khởi tạo các trường một cách lười biếng; nó có thể lặp lại quá trình khởi tạo lười biếng đó khi nhận dữ liệu. Ngay cả khi mã code khởi tạo các trường này một cách hăng hái, nó vẫn có thể đành dấu bất kỳ trường được tính toán nào là tạm thời và tính toán lại giá trị của chúng trong phương thức `readObject()` của lớp. + +Cũng lưu ý rằng điều này duy trì mối quan hệ đối tượng giữa giá và các đối tượng biểu đồ: khi biểu đồ được tính toán lại, nó chỉ thêm các đối tượng hiện có bàn bản đồ mới. + +Loại tối ưu hoá này luôn luôn là một điều tốt, nhưng có những trường hợp nó thực sự có thể ảnh hưởng đến hiệu suất. Bảng 1: cho thấy thời gian cần thiết để tuần tự hoá và giải mã trong trường hợp này trong đó đối tượng biểu đồ là tạm thời so với không tạm thời, cũng như kích thước dữ liệu được tuần tự hoá cho từng trường hợp. + +Bảng 1: Thời gian tuần tự hoá và giải mã đối tượng với các trường được đánh dấu tạm thời +![Bảng 1](/assets/images/posts/2022-10-25/serialization-1.png) + +Cho đến nay, ví dụ này tiết kiệm khoảng 15% tổng thời gian để tuần tự hoá và giải mã đối tượng. Nhưng thử nghiệm này chưa thực sự tạo lại đối tượng biểu đồ ở phía nhận: đối tượng đó sẽ được tao khi mã nhận truy cập lần đầu tiên. + +Đôi khi đối tượng biểu đồ sẽ không cần thiết: khách hàng chỉ quan tâm đến giá vào những ngày cụ thể chứ không quan tâm đến biểu đồ. Đó là trường hợp bất thường xảy ra: nếu biểu đồ sẽ luôn cần thiết, và nếu mất hơn 3.1 giây để tính toán tất cả các biểu đồ trong thử nghiệm này, thì trường hợp với các trường được khởi tạo lười biếng sẽ thực sự có hiệu xuất giảm. + +Trong trường hợp này, tính toán biểu đồ không thuộc loại đó -- đó là một tính toán rất nhanh. Nói chung, có thể khó tìm thấy trường hợp tính toán lại một phần dữ liệu tốn chi phí hơn việc tuần tự hoá và giải mã dữ liệu đó. Nhưng nó là một cái gì đó để cân nhắc như mã code tối ưu hoá. + +Thử nghiệm này không thực sự truyền dữ liệu; dữ liệu được ghi vào và đọc ra từ các mảng byte được gán sẵn, đo đó nó chỉ đo thời gian cho tuần tự hoá và giải mã. Tuy nhiên, hãy lưu ý rằng việc tạo trường biểu đồ tạm thời cũng đã tiết kiệm được khoảng 13% kích thước dữ liệu. Điều đó khá quan trọng nếu dữ liệu được truyền qua mạng. + +### Nén dữ liệu đã được tuần tự hoá +Điều này dẫn đến cách thứ 3 mà hiệu suất tuần tự hoá của mã code có thể được cải thiện: nén dữ liệu tuần tự hoá để truyền nhanh hơn qua mạng chậm. Trong lớp lịch sử hàng tồn kho, nó được thực hiện bằng cách nén bản đồ giá trong quá trình tuần tự hoá: +```java +public class StockPriceHistoryCompress implements StockPriceHistory, Serializable { + private byte[] zippedPrices; + private transient SortedMap prices; + private void writeObject(ObjectOutputStream out) throws IOException { + if (zippedPrices == null) { + makeZippedPrices(); + } + out.defaultWriteObject(); + } + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + unzipPrices(); + } + protected void makeZippedPrices() throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + GZIPOutputStream zip = new GZIPOutputStream(baos); + ObjectOutputStream oos = new ObjectOutputStream(new BufferedOutputStream(zip)); + oos.writeObject(prices); + oos.close(); + zip.close(); + zippedPrices = baos.toByteArray(); + } + protected void unzipPrices() throws IOException, ClassNotFoundException { + ByteArrayInputStream bais = new ByteArrayInputStream(zippedPrices); + GZIPInputStream zip = new GZIPInputStream(bais); + ObjectInputStream ois = new ObjectInputStream(new BufferedInputStream(zip)); + prices = (SortedMap) ois.readObject(); + ois.close(); + zip.close(); + } +} +``` +Phương thức `makeZippedPrices()` tuần tự hoá bàn đồ giá thành mảng byte và lưu các byte kết quả, sau đó tuần tự hoá bình thường trong phương thức `writeObject()` khi nó gọi phương thức `defaultWriteObject()`. (Trên thực tế, miễn là quá trình tuần tự hoá đang được tuỳ chỉnh, sẽ tốt hơn một chút nếu đánh dấu mảng `zippedPrices` là tạm thời và viết ra độ dài byte một các trực tiếp. Nhưng mã code này rõ ràng hơn, và đơn giản là tốt hơn) Trên quá trình giải mã, tính toán ngược lại được thực hiện. + +Nếu mục tiêu là tuần tự hoá thành một mảng byte (như trong mã mẫu ban đầu), thì đây là một mệnh đề thất bại. Điều đó không có gì đáng ngạc nhiên; thời gian cần thiết để nén các byte lâu hơn nhiều so với thời gian ghi chúng vào một mảng byte cục bộ. Thời gian được thể hiện trong bảng 2. + +Bảng 2: Thời gian tuần tự hoá và giải mã 10,000 đối tượng với nén +![Bảng 2](/assets/images/posts/2022-10-25/serialization-3.png) + +Điểm thú vị nhất về bảng này là dòng cuối cùng. Trong thử ngiệm đó, dữ liệu được nén trước khi gửi, nhưng phương thức `unzipPrices()` không gọi phương thức `readObject()`. Thay vào đó, nó được gọi khi cần thiết, đó là lần đâu tiên khách hàng gọi phương thức `getPrice()`. Không có gọi lệnh đó, chỉ có một số đối tượng BigDecimal được giải mã, khá nhanh. + +Trong ví dụ này, rất có thể khách hàng sẽ không bao giờ cần giá trị thực tế: khách hàng chỉ cần gọi hàm getHightPrice() và các phương thức tương tự để truy xuất thông tin tổng hợp về dữ liệu. Miễn là những phương thức đó là tất cả những gì cần thiết, có thể tiết kiệm rất nhiều thời gian bằng cách giải nén thông tin giá một cách lười biếng. Giải nén lười biếng này cũng khá hưu ích nếu đối tượng được đề cập đang được duy trì (ví dụ: nếu đó là trang thái của phiên làm việc HTTP đang được lưu trữ dưới dạng bản sao trong trường hợp máy chủ bị lỗi). Giải nén một cách lười biếng giúp tiết kiệm thời gian của CPU (từ việc bỏ qua giải nén) và bộ nhớ (vì dữ liệu nén chiếm ít dung lượng hơn). + +Vì vậy, ngay cả khi ứng dụng được chạy ở mạng cục bộ, tốc độ cao - và rõ ràng nếu mục đích là tiết kiệm bộ nhớ hơn là thời gian - thì việc nén dữ liệu để tuần tự hoá và sau đó giải nén một cách lười biếng nó có thể khá hữu ích. + +Nếu mục đích của tuần tự hoá là để truyền dữ liệu qua mạng, thì nén sẽ giàng chiến thằng bất kỳ lúc nào có dữ liệu tiết kiệm. Bảng 3 thực hiện tuần tự hoá tương tự cho 10,000 đối tượng hàng tồn kho, nhưng lần này nó lại truyền dữ liệu qua một tiến trình khác. Tiến trình khác hoặc chạy trên cùng 1 máy, hoặc trên một máy được truy cập thông qua kết nối băng thông rộng của tôi. + +Bảng 3: Thời gian truyền tải 10,000 đồi tượng qua mạng +![Bảng 3](/assets/images/posts/2022-10-25/serialization-3.png) + +Giao tiếp mạng nhanh nhất là giao tiếp giữa 2 tiến trình trên cùng 1 máy - giao tiếp đó hoàn toàn không đi qua mạng, mặc dù nó gửi dữ liệu thông qua giao diện của hệ điều hành. Ngay cả trong trường hợp đó, việc nén dữ liệu và giải nén dữ liệu một cách lười biếng đã dần đạt tới hiệu quả nhanh nhất (ít nhất đối với thử nghiệm này). Và thứ tự chênh lệch về độ lớn trong lượng dữ liệu đã tạo ra khác biệt lớn (có thể dự đoán được) trong tổng thời gian khi một mạng chậm hơn tham gia. + +### Theo dõi các đối tượng trùng lặp +Phần này bắt đầu với một ví dụ về cách không tuần tự hoá dữ liệu có chứa các tham chiếu dữ liệu, để tránh các tham chiếu đối tượng bị xâm phạm khi dữ liệu được giải mã. Tuy nhiên, một trong nhưng cách tối ưu hoá manh mẽ hơn có thể có trong phương thức `writeObject()` là không viết ra các tham chiếu đối tượng trùng lặp. Trong trường hợp của lớp `StockPriceHistoryImpl`, điều đó có nghĩa là không viết ra các tham chiếu trùng lặp của bàn đồ giá. Bời vì ví dụ sử dụng một lớp JDK tiêu chuẩn cho bản đồ đó, chúng ta không cần lo lắng về điều đó: các lớp JDK đã được viết để tuần tự hoá một các tối ưu. Tuy nhiên, cần xem xét các lớp đó thực hiện tối ưu hoá như thế nào để hiểu điều gì có thể xảy ra. + +Trong lớp `StockPriceHistoryImpl`, cấu trúc khoá là một sơ đồ cây. Một phiên bản đơn giản của bản đồ đó xuất hiện trong hình 1 với tuần tự hoá mặc định, JVM sẽ ghi ra các trường dữ liệu ban đầu cho node A; thì nó sẽ gọi đệ quy phương thức `writeObject()` cho node B (và sau đó cho node C). Mã code cho node B có thể viết ra trường dữ liệu ban đầu của nó, và sau đó đệ quy viết ra dữ liệu cho trường cha của nó. + +Nhưng chờ một chút - trường cha đó là node A, đã được viết. Mã tuần tự hoá đối tượng đủ thông minh để nhận ra rằng: nó không viết lại dữ liệu cho node A. Thay vào đó, nó chỉ thêm một tham chiếu đối tượng và dữ liệu đã được ghi trước đó. + +Theo dõi tập hợp các đối tượng viết trước đó, cũng như tất cả các đệ quy đó, sẽ thêm một hiệu xuất nhỏ vào tuần tự hoá đối tượng. Tuy nhiên, như được minh hoạ trong ví dụ vói một mảng của đối tượng điểm, nó không thể tránh được điều này: mã code phải theo dõi đối tượng viết ra trước đó và tạo lại các tham chiếu đối tượng chính xác. Tuy nhiên, có thể thực hiện tối ưu hoá thông minh bằng cách loại bỏ các tham chiếu đối tượng có thể dễ dàng tạo lại khi đối tượng được giải mã. + +Hình 1: Cấu trúc sơ đồ cây đơn giản +![Hình 1](/assets/images/posts/2022-10-25/serialization-f-1.png) + +Các bộ sưu tập khác nhau xử lý điều này theo cách khác nhau. Ví dụ, lớp TreeMap chỉ đơn giản lặp qua cây và chỉ ghi lại các khoá và giá trị; tuần tự hoá loại bỏ tất cả các thông tin về mối quan hệ giữa các khoá (tức là thứ tự sắp xếp của chúng). Khi dữ liệu đã được giải mã, phương thức `readObject()` sẽ sắp xếp lại dữ liệu để tạo ra một cây. Mặc dù sắp xếp lại đối tượng nghe có vẻ tốn kém, nhưng không phải vậy: quá trình đó nhanh hơn khoảng 20% trên một tập hợp 10,000 đối tượng hàng tồn kho so với việc sử dụng tuần tự hoá mặc định, theo đuổi tất cả các tham chiếu đối tượng. + +Lớp TreeMap cũng được hưởng lợi từ việc tối ưu hoá bời vì nó có thể viết ra ít đối tượng hơn. Một node (hoặc trong ngôn ngữ JDK, một Entry) trong bản đồ chứa 2 đối tượng: khoá và giá trị. Bởi vì bản đồ không thể chứa 2 node giống nhau, mã code tuần tự hoá không cần lo lắng về việc bảo toàn các tham chiếu đối tượng đến các node. Trong trường hợp này, nó có thể bỏ qua việc viết đối tượng node chính nó, và đơn giảm chỉ ghi trực tiếp các đối tượng khoá và giá trị. Vì vậy, phương thức `writeObject()` trông giống như thế này (cú pháp điều chỉnh cho dễ đọc): +```java +private void writeObject(ObjectOutputStream oos) throws IOException { + .... + for (Map.Entry e : entrySet()) { + oos.writeObject(e.getKey()); + oos.writeObject(e.getValue()); + } + .... +} +``` +Điều này trông rất giống với mã code không hoạt động cho ví dụ Point. Sự khác biệt trong trường hợp này là mã code vẫn đang viết các đối tượng trong đó các đối tượng đó có thể giống nhau. Bản đồ cây không thể có 2 node giống nhau, vì vậy không cần phải viết ra node tham chiếu. Bản đồ cây có thể có 2 giá trị giống nhau, vì vậy các giá trị phải được viết dưới dạng tham chiếu đối tượng. + +Điều này mang lại cho chúng ta một vòng tròn đầy đủ: như tôi đã nêu ở đầu phần này, việc tối ưu hoá đối tượng tuần tự hoá chính xác có thể rất khó. Nhưng khi tuần tự hoá đối tượng là một nút thắt cổ chai đáng kể trong ứng dụng, việc tối ưu hoá chúng 1 cách chính xác có thể mang lại lợi ích quan trọng. + +### Điều gì về Externalizable? +Phần này chưa nói về một cách tiếp cận khác để tối ưu tuần tự hoá đối tượng, đó là triển khai giao diện Externalizable chứ không phải là giao diện Serializable. + +Sự khác biệt thực tế giữa 2 giao diện này là chúng xử lý các trường được đánh dấu là tạm thời. Giao diện Serializable viết ra các trường không được đánh dấu khi phương thức `writeObject()` gọi phương thức `defaultWriteObject()`. Giao diện Externalizable không có phương thức như vậy. Lớp Externalizable phải viết rõ ràng ra tất cả các trường, tạm thơi hoặc không, mà nó quan tâm đến trong khi truyền. + +Nếu như tất cả các trường trong đối tượng là tạm thời, tốt hơn là nên trên khai giao diện Serializable và gọi phương thức `defaultWriteObject()`. Điều đó dẫn đến mã code dễ bảo trì hơn nhiều khi các đối tượng được thêm vào (và xoá khỏi) mã code. Và không có lợi ích cố hưu nào đối với giao diện Externalizable từ quan điểm hiệu xuất: cuối cùng, điều quan trọng là số lượng dữ liệu được ghi. + +### Tóm tắt nhanh +1. Tuần tự hoá dữ liệu, đặc biệt trong Java EE, có thể là một điểm nghẽn hiệu xuất lớn +2. Đánh dấu các biến là tạm thời sẽ giúp tuần tự hoá nhanh hơn và giảm lượng dữ liệu được truyền tải. Cả 2 điều đó thường là những chiến thắng hiệu xuất lớn, trừ khi việc tạo lại dữ liệu trên nơi nhận mất một thời gian rất dài. +3. Các tối ưu khác thông qua phương thức `writeObject()` và `readObject()` có thể tăng tốc tuần tự hoá một cách đáng kể. Tiếp cận chúng một cách thận trong, vì rất dễ mắc lỗi và tạo ra một lỗi khó phát hiện. +4. Nén dữ liệu tuần tự hoá thường có lợi, ngay cả khi dữ liệu không truyền qua mạng chậm + +## Refs: +1. Sách Java Performance - The Definitive Guide diff --git a/assets/images/avatars/blu3.jpg b/assets/images/avatars/blu3.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ecf6272be2bdaaa9258540ee71287f5fdb4a85ba GIT binary patch literal 25131 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 literal 0 HcmV?d00001 diff --git a/assets/images/posts/2022-10-25/serialization-1.png b/assets/images/posts/2022-10-25/serialization-1.png new file mode 100644 index 0000000000000000000000000000000000000000..3b583a9047ef5e7befef224b36dcc2fac74c7a50 GIT binary patch literal 15526 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 DH%nUS literal 0 HcmV?d00001 diff --git a/assets/images/posts/2022-10-25/serialization-2.png b/assets/images/posts/2022-10-25/serialization-2.png new file mode 100644 index 0000000000000000000000000000000000000000..0bd7c800e7d6c8172eb62b6defc08add691776e1 GIT binary patch literal 21217 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

k-IiGr_Ty;*hNT-F^xv2 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 literal 0 HcmV?d00001 diff --git a/assets/images/posts/2022-10-25/serialization-3.png b/assets/images/posts/2022-10-25/serialization-3.png new file mode 100644 index 0000000000000000000000000000000000000000..732fce4fe66e4a21ce992d5c2bb0f1b2dcff20a3 GIT binary patch literal 15276 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 P%hIVRYARIAnFs$L9fyw3 literal 0 HcmV?d00001 From 2cb05f85123a682874144548b8df76dabad117b5 Mon Sep 17 00:00:00 2001 From: hoanthetran Date: Fri, 28 Oct 2022 11:11:17 +0700 Subject: [PATCH 2/3] revert Gemfile.lock --- Gemfile.lock | 84 ++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 45 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 88a1028..b8a4ce2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,76 +1,70 @@ GEM remote: https://rubygems.org/ specs: - addressable (2.8.1) - public_suffix (>= 2.0.2, < 6.0) + addressable (2.6.0) + public_suffix (>= 2.0.2, < 4.0) colorator (1.1.0) - concurrent-ruby (1.1.10) - em-websocket (0.5.3) + concurrent-ruby (1.1.5) + em-websocket (0.5.1) eventmachine (>= 0.12.9) - http_parser.rb (~> 0) + http_parser.rb (~> 0.6.0) eventmachine (1.2.7) - ffi (1.15.5) + ffi (1.10.0) forwardable-extended (2.6.0) - http_parser.rb (0.8.0) - i18n (1.12.0) + http_parser.rb (0.6.0) + i18n (0.9.5) concurrent-ruby (~> 1.0) - jekyll (4.3.0) + jekyll (3.8.5) addressable (~> 2.4) colorator (~> 1.0) em-websocket (~> 0.5) - i18n (~> 1.0) - jekyll-sass-converter (>= 2.0, < 4.0) + i18n (~> 0.7) + jekyll-sass-converter (~> 1.0) jekyll-watch (~> 2.0) - kramdown (~> 2.3, >= 2.3.1) - kramdown-parser-gfm (~> 1.0) + kramdown (~> 1.14) liquid (~> 4.0) - mercenary (>= 0.3.6, < 0.5) + mercenary (~> 0.3.3) pathutil (~> 0.9) - rouge (>= 3.0, < 5.0) + rouge (>= 1.7, < 4) safe_yaml (~> 1.0) - terminal-table (>= 1.8, < 4.0) - webrick (~> 1.7) - jekyll-feed (0.17.0) + jekyll-feed (0.12.1) jekyll (>= 3.7, < 5.0) jekyll-paginate (1.1.0) - jekyll-sass-converter (2.2.0) - sassc (> 2.0.1, < 3.0) - jekyll-sitemap (1.4.0) + jekyll-sass-converter (1.5.2) + sass (~> 3.4) + jekyll-sitemap (1.3.1) jekyll (>= 3.7, < 5.0) jekyll-watch (2.2.1) listen (~> 3.0) - kramdown (2.4.0) - rexml - kramdown-parser-gfm (1.1.0) - kramdown (~> 2.0) + kramdown (1.17.0) liquid (4.0.3) - listen (3.7.1) - rb-fsevent (~> 0.10, >= 0.10.3) - rb-inotify (~> 0.9, >= 0.9.10) - mercenary (0.4.0) - msgpack (1.6.0) - multi_json (1.15.0) - neovim (0.9.0) + listen (3.1.5) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) + ruby_dep (~> 1.2) + mercenary (0.3.6) + msgpack (1.2.9) + multi_json (1.13.1) + neovim (0.8.0) msgpack (~> 1.1) multi_json (~> 1.0) pathutil (0.16.2) forwardable-extended (~> 2.6) - public_suffix (5.0.0) - rb-fsevent (0.11.2) - rb-inotify (0.10.1) + public_suffix (3.0.3) + rb-fsevent (0.10.3) + rb-inotify (0.10.0) ffi (~> 1.0) - rexml (3.2.5) - rouge (4.0.0) + rouge (3.3.0) + ruby_dep (1.5.0) safe_yaml (1.0.5) - sassc (2.4.0) - ffi (~> 1.9) - terminal-table (3.0.2) - unicode-display_width (>= 1.1.1, < 3) - unicode-display_width (2.3.0) - webrick (1.7.0) + sass (3.7.4) + sass-listen (~> 4.0.0) + sass-listen (4.0.0) + rb-fsevent (~> 0.9, >= 0.9.4) + rb-inotify (~> 0.9, >= 0.9.7) PLATFORMS - arm64-darwin-20 + ruby DEPENDENCIES jekyll (>= 3.6.3) @@ -82,4 +76,4 @@ DEPENDENCIES rouge BUNDLED WITH - 2.2.22 + 1.13.6 From 9754b2164c4f4e399cc54471a0617fec18306931 Mon Sep 17 00:00:00 2001 From: hoanthetran Date: Tue, 15 Nov 2022 17:03:07 +0700 Subject: [PATCH 3/3] improve translate --- .../2022-10-25-java-object-serialization.md | 98 +++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/_posts/2022-10-25-java-object-serialization.md b/_posts/2022-10-25-java-object-serialization.md index 647b922..4cc9dae 100644 --- a/_posts/2022-10-25-java-object-serialization.md +++ b/_posts/2022-10-25-java-object-serialization.md @@ -11,19 +11,19 @@ description: > ## Objects Serialization performance -XML, JSON, và định dạng tương tự như text-based chúng rất hữu ích cho việc trao đổi dữ liệu giữa các hệ thống. Giữa các tiến trình trong Java, dữ liệu thường được trao đổi thông qua trạng thái tuần tự hoá của một đối tượng. Mặc dù nó được sử dụng rộng rãi trong Java, tuần tự hoá có 2 quan điểm quan trọng cần xem xét trong Java EE: -- EJB được gọi giữa các máy chủ Java EE - EJB gọi từ xa - Sử dụng tuần tự hoá để trao đổi dữ liệu -- Trạng thái phiên làm việc của giao thức HTTP được lưu thông qua tuần tự hoá đối tượng, điều này cho phép các phiên làm việc thông qua giao thức HTTP có tính khả dụng cao. +XML, JSON, và định dạng tương tự như text-based chúng rất hữu ích trong việc trao đổi dữ liệu giữa các hệ thống với nhau. Giữa các tiến trình trong Java, dữ liệu thường được trao đổi thông qua trạng thái `serialization` của một đối tượng. Mặc dù nó được sử dụng rộng rãi trong Java, `serialization` có 2 điểm quan trọng cần quan tâm trong Java EE: +- EJB được gọi giữa các máy chủ Java EE với nhau - EJB gọi từ xa - Sử dụng `serialization` để trao đổi dữ liệu +- Trạng thái HTTP session được lưu thông qua `serialization` của đối tượng, điều này làm cho các HTTP session có tính sẳn sàng cao. -JDK cung cấp một cơ chế mặc định để tuần tự hoá các đối tượng thông qua triển khai giao diện Serializable hoặc giao diện Externalizable. Trên thực tế, hiệu suất tuần tự hoá của mọi đối tượng có thể được cải thiện từ tuần tự hoá mặc định, nhưng chắc chắn ngay từ đầu không phải là thời điểm thích hợp để thực hiện tối ưu tuần tự hoá. Mã code đặc biệt để serialize và deserialize sẽ tốn thời gian để viết, và Mã code sẽ khó bảo trì hợn so với cơ chế mặc định. Mã code tuần tự hoá cũng có thể phức tạp, vì vậy việc cố gắng tối ưu hoá nó sẽ làm tăng nguy cơ tạo ra mã code không chính xác. +JDK cung cấp một cơ chế mặc định để `serialization` các đối tượng thông qua implement giao diện `Serializable` hoặc giao diện `Externalizable`. Trên thực tế, hiệu suất của quá trình `serialization` đối với mọi đối tượng có thể được cải thiện từ mã code `serialization` mặc định, nhưng đây chắc chắn không phải là thời điểm khôn ngoàn để tối ưu hiệu xuất `serialization` sớm. Đoạn mã code đặc biệt để `serialization` và `deserialization` sẽ tốn thời gian để viết, và mã code đó cũng sẽ khó bảo trì hơn so với mã code `serilization` mặc định. Mã code `serialization` cũng có thể phức tạp, vì vậy việc cố gắng tối ưu hoá nó sẽ làm tăng nguy cơ tạo ra bug. ### Transient Fields -Nói chung, cách để cải thiện chi phí tuần tự hoá đối tượng là tuần tự hoá ít dữ liệu nhất có thể. Điều này được thực hiện bằng cách đánh dấu các trường không cần thiết là tạm thời. Khi được đánh dấu tạm thời chúng sẽ không được tuần tự hoá theo mặc định. Sau đó, lớp có thể cung cấp các phương thức `writeObject()` và `readObject()` đặc biệt để xử lý dữ liệu đó. +Nói chung, cách để cải thiện chi phí `serialization` đối tượng là `serialization` ít dữ liệu nhất có thể. Điều này được thực hiện bằng cách đánh dấu các trường không cần thiết là `transient`. Khi được đánh dấu là `transient` theo mặc định chúng sẽ không được `serialization`. Sau đó, class có thể cung cấp các phương thức `writeObject()` và `readObject()` đặc biệt để xử lý dữ liệu đó. ### Overriding Default Serialization -Phương thức `writeObject()` và `readObject()` cho phép kiểm soát hoàn toàn dữ liệu được tuần tự hoá. Với khả năng kiểm soát tốt đi kèm với trách nhiệm lớn: điều này rất dễ mắc sai lầm. +Phương thức `writeObject()` và `readObject()` cho phép kiểm soát hoàn toàn dữ liệu được `serialization` như thế nào. Với sự kiểm soát quan trọng đi kèm với trách nhiệm quan trọng: điều này rất dễ mắc sai lầm. -Để biết được lý do tại sao tối ưu hoá tuần tự hoá là phức tạp, hãy lấy trường hợp của một đối tượng Point đơn giản đại diện cho vị trí: +Để biết được lý do tại sao tối ưu hoá `serialization` là phức tạp, hãy lấy trường hợp của một đối tượng Point đơn giản đại diện cho vị trí: ```java public class Point implements Serializable { private int x; @@ -31,7 +31,7 @@ public class Point implements Serializable { ... } ``` -Trên máy tính của tôi, 100.000 đối tượng trong số này được tuần tự hoá trong 113 mili giây và được giải mã trong 741 mili giây. Nhưng ngay cả khi đối tượng đó đơn giản như vậy, nó có thể rất, rất khó để đạt được hiệu xuất được cải thiện: +Trên máy tính của tôi, 100.000 đối tượng trong số này được `serialization` trong 113 mili giây và được `deserialization` trong 741 mili giây. Nhưng ngay cả khi đối tượng đơn giản như vậy, vẫn rất khó để đạt được hiệu xuất được cải thiện: ```java public class Point implements Serializable { private transient int x; @@ -50,7 +50,7 @@ public class Point implements Serializable { } } ``` -Việc tuần tự hoá 100.000 đối tượng trên máy tính của tôi vẫn mất 132 mili giây, nhưng việc giải mã tuần tự chỉ mất 468 mili giây (cải thiện 30% hiệu suất). Nếu giải mã một đối tượng đơn giản là điều chiếm 1 phần đáng kể trong một chương trình, thì việc tối ưu hoá như này có thể là hợp lý. Tuy nhiên, hãy lưu ý nó làm cho mã code khó bảo trì hơn khi các trường được thêm vào, di chuyển... +Việc `serialization` 100.000 đối tượng trên máy tính của tôi vẫn mất 132 mili giây, nhưng việc `deserialization` chỉ mất 468 mili giây (cải thiện 30% hiệu suất). Nếu `deserialization` một đối tượng đơn giản là điều chiếm 1 phần đáng kể trong một chương trình, thì việc tối ưu hoá như này có thể là hợp lý. Tuy nhiên, hãy lưu ý nó làm cho mã code khó bảo trì hơn khi các trường được thêm vào, di chuyển... Tuy nhiên cho tới lúc này, mã code phức tạp hơn nhưng vẫn đúng về mặt chức năng (và nhanh hơn). Nhưng hãy cần thận khi sử dụng kỹ thuật này trong trường hợp chung: ```java @@ -77,17 +77,17 @@ public class TripHistory implements Serializable { } } ``` -Ở đây trường `airportsVisited` là 1 mảng chứa tất cả sân bay được tôi ghé thăm, sắp xếp theo thứ tự mà tôi đã đến thăm chúng. Vì vậy một số sân bay nhất định như JKF xuất hiện thường xuyên trong mảng; SYD chỉ xuất hiện 1 lần (cho đến nay). +Ở đây trường `airportsVisited` là 1 mảng chứa tất cả sân bay được tôi ghé thăm, sắp xếp theo thứ tự mà tôi đã đến thăm chúng. Vì vậy một số sân bay nhất định như JKF xuất hiện thường xuyên trong mảng; SYD chỉ xuất hiện 1 lần. -Bởi vì tốn công viết mã tham chiếu đối tượng, mã này chắc chắn sẽ hoạt động nhanh hơn cơ chế tuần tự hoá mặc định cho mảng đó: Một mảng 100.000 đối tượng Point mất 4,7 giây để tuần tự hoá trên máy của tôi và 6,9 giây để giải mã. Bằng cách sử dụng "tối ưu hoá" ở trên, chỉ mất 2 giây để tuần tự hoá và 1.7 giây để giải mã. +Bởi vì tốn công viết mã code tham chiếu đối tượng, mã code này chắc chắn sẽ hoạt động nhanh hơn cơ chế `serialization` mặc định cho mảng đó: Một mảng 100.000 đối tượng Point mất 4,7 giây để `serialization` trên máy của tôi và 6,9 giây để `deserialization`. Bằng cách sử dụng "tối ưu hoá" ở trên, chỉ mất 2 giây để `serialization` và 1.7 giây để `deserialization`. -Tuy nhiên mã này chạy không chính xác. Các tham chiếu trong mảng chỉ định vị trí của JFK đầu bắt đầu tham chiếu đến cùng 1 đối tượng . Điêu đó có nhĩa là khi tôi phát hiện ra rằng vị trí được trình bày trong dữ liệu là không chính xác, một JFK đơn lẻ có thể bị thay đổi và tất cả các đối tượng trong mảng cũng sẽ thay đổi theo (vì chúng cùng tham chiếu đến 1 đối tượng). +Tuy nhiên mã này chạy có `bug`. Các tham chiếu trong mảng chỉ định vị trí của JFK đều tham chiếu đến cùng 1 đối tượng . Có nghĩa là khi tôi phát hiện ra rằng vị trí được trình bày trong dữ liệu là không chính xác, tham chiếu JFK duy nhất có thể bị thay đổi và tất cả các đối tượng trong mảng cũng sẽ thay đổi theo (vì chúng cùng tham chiếu đến 1 đối tượng). -Khi mảng được giải mã bằng mã code trên, các tham chiếu JFK đó sẽ trở thành các đối tượng riêng biệt, khác nhau. Bây giờ khi một trong những đối tượng bị thay đổi, chỉ đối tượng đó bị thay đổi. Các đối tượng còn lại vẫn tham chiếu đên JFK. +Khi mảng được `deserialization` bằng mã code trên, các tham chiếu JFK đó sẽ trở thành các đối tượng riêng biệt, khác nhau. Bây giờ khi một trong những đối tượng bị thay đổi, chỉ đối tượng đó bị thay đổi. Các đối tượng còn lại vẫn tham chiếu đên JFK. -Đây là một nguyên tắc quan trọng cần nhớ, bởi vì tối ưu tuần tự hoá thường là xử lý đặc biệt cho các tham chiếu đối tượng. Thực hiện chính xác có thể làm tăng đáng kể hiệu xuất, thực hiện không chính xác nó có thể phát sinh các lỗi khá tinh vi. +Đây là một nguyên tắc quan trọng cần nhớ, bởi vì tối ưu `serialization` thường là xử lý đặc biệt cho các tham chiếu đối tượng. Thực hiện chính xác có thể làm tăng đáng kể hiệu xuất, thực hiện không chính xác nó có thể phát sinh các lỗi khá tinh vi. -Với suy nghĩ đó, hãy cùng khám phá quá trình tuần tự hoá của lớp `StockPriceHistory` để xem cách tối ưu hoá có thể được thực hiện như thế nào. +Với suy nghĩ đó, hãy cùng khám phá quá trình `serialization` của lớp `StockPriceHistory` để xem cách tối ưu hoá có thể được thực hiện như thế nào. ```java public class StockPriceHistoryImpl implements StockPriceHistory { private String symbol; @@ -106,29 +106,29 @@ public class StockPriceHistoryImpl implements StockPriceHistory { } } ``` -Khi lịch sử của hàng tồn kho được xây dựng trên ký hiệu `s`, đối tượng được tạo và lưu trữ trên một bản đồ giá được sắp xếp theo ngày của tất cả các giá từ đầu đến cuối. Mã code cũng lưu lại ngày đầu tiên và ngày cuối cùng. Hàm tạo không điền vào bất kỳ một trường nào khác, chúng được tạo một cách lười biếng. Khi một getter trên bất kỳ trường nào được gọi, getter sẽ kiểm tra xem `needsCalc` có đúng không. Nếu có, nó sẽ tính toán các giá trị thích hợp cho tất cả các trường còn lại nếu cần (tất cả cùng một lúc). +Khi lịch sử của hàng tồn kho được xây dựng trên ký hiệu `s`, đối tượng được tạo và lưu trữ trên một bản đồ giá được sắp xếp theo ngày của tất cả các giá từ đầu đến cuối. Mã code cũng lưu lại ngày đầu tiên và ngày cuối cùng. Hàm tạo không điền vào bất kỳ một trường nào khác, chúng được khởi tạo theo kiểu `lazy`. Khi một `getter` trên bất kỳ trường nào được gọi, `getter` sẽ kiểm tra xem `needsCalc` có đúng không. Nếu có, nó sẽ tính toán các giá trị thích hợp cho tất cả các trường còn lại nếu cần (tất cả cùng một lúc). -Tính toán này bao gồm việc tạo biểu đồ, ghi lại số ngày hàng tồn kho đóng lại ở một mức giá cụ thể. Biểu đồ chứa đựng cùng một dữ liệu ?(về đối tường `BigDecimal` và `Date`) như được tìm thấy trong bản đồ giá; nó chỉ là một cách nhìn khác về dữ liệu. +Tính toán này bao gồm việc tạo biểu đồ, ghi lại số ngày hàng tồn kho được chốt ở một mức giá cụ thể. Biểu đồ chứa đựng cùng một dữ liệu (về đối tường `BigDecimal` và `Date`) như được tìm thấy trong bản đồ giá; nó chỉ là một cách nhìn khác về dữ liệu. -Bởi vì tất cả các trường được khởi tạo một cách lười biếng có thể tính toán từ mảng giá, tất cả chúng có thể được đánh dấu tạm thời, và không cần thực hiện công việc đặc biệt nào để tuần tự hoá và giải mã chúng. Ví dụ này rất dễ dàng trong trường hợp này vì mã code đã thực hiện việc khởi tạo các trường một cách lười biếng; nó có thể lặp lại quá trình khởi tạo lười biếng đó khi nhận dữ liệu. Ngay cả khi mã code khởi tạo các trường này một cách hăng hái, nó vẫn có thể đành dấu bất kỳ trường được tính toán nào là tạm thời và tính toán lại giá trị của chúng trong phương thức `readObject()` của lớp. +Bởi vì tất cả các trường được khởi tạo theo kiểu `lazy` có thể tính toán từ mảng giá, tất cả chúng có thể được đánh dấu `transient`, và không cần thực hiện công việc đặc biệt nào để `serialization` và `deserialization` chúng. Ví dụ này rất dễ dàng trong trường hợp này vì mã code đã thực hiện việc khởi tạo các trường theo kiểu `lazy`; nó có thể lặp lại quá trình khởi tạo theo kiểu `lazy` khi nhận dữ liệu. Ngay cả khi mã code khởi tạo các trường này theo kiểu `eager`, nó vẫn có thể đánh dấu bất kỳ trường được tính toán nào là `transient` và tính toán lại giá trị của chúng trong phương thức `readObject()` của lớp. -Cũng lưu ý rằng điều này duy trì mối quan hệ đối tượng giữa giá và các đối tượng biểu đồ: khi biểu đồ được tính toán lại, nó chỉ thêm các đối tượng hiện có bàn bản đồ mới. +Lưu ý rằng điều này duy trì mối quan hệ đối tượng giữa giá và các đối tượng biểu đồ: khi biểu đồ được tính toán lại, nó chỉ thêm các đối tượng hiện có vào `map` mới. -Loại tối ưu hoá này luôn luôn là một điều tốt, nhưng có những trường hợp nó thực sự có thể ảnh hưởng đến hiệu suất. Bảng 1: cho thấy thời gian cần thiết để tuần tự hoá và giải mã trong trường hợp này trong đó đối tượng biểu đồ là tạm thời so với không tạm thời, cũng như kích thước dữ liệu được tuần tự hoá cho từng trường hợp. +Loại tối ưu hoá này luôn luôn tốt, nhưng có những trường hợp nó thực sự có thể ảnh hưởng đến hiệu suất. Bảng 1: cho thấy thời gian cần thiết để `serialization` và `deserialization` trong trường hợp này trong đó đối tượng biểu đồ là `transient` so với không `transient`, cũng như kích thước dữ liệu được `serialization` cho từng trường hợp. -Bảng 1: Thời gian tuần tự hoá và giải mã đối tượng với các trường được đánh dấu tạm thời +Bảng 1: Thời gian `serialization` và `deserialization` đối tượng với các trường được đánh dấu `transient` ![Bảng 1](/assets/images/posts/2022-10-25/serialization-1.png) -Cho đến nay, ví dụ này tiết kiệm khoảng 15% tổng thời gian để tuần tự hoá và giải mã đối tượng. Nhưng thử nghiệm này chưa thực sự tạo lại đối tượng biểu đồ ở phía nhận: đối tượng đó sẽ được tao khi mã nhận truy cập lần đầu tiên. +Cho đến nay, ví dụ này tiết kiệm khoảng 15% tổng thời gian để `serialization` và `deserialization` đối tượng. Nhưng thử nghiệm này chưa thực sự tạo lại đối tượng biểu đồ ở phía nhận: đối tượng đó sẽ được tạo khi truy cập lần đầu tiên. -Đôi khi đối tượng biểu đồ sẽ không cần thiết: khách hàng chỉ quan tâm đến giá vào những ngày cụ thể chứ không quan tâm đến biểu đồ. Đó là trường hợp bất thường xảy ra: nếu biểu đồ sẽ luôn cần thiết, và nếu mất hơn 3.1 giây để tính toán tất cả các biểu đồ trong thử nghiệm này, thì trường hợp với các trường được khởi tạo lười biếng sẽ thực sự có hiệu xuất giảm. +Đôi khi đối tượng biểu đồ sẽ không cần thiết: khách hàng chỉ quan tâm đến giá vào những ngày cụ thể chứ không quan tâm đến biểu đồ. Đó là trường hợp bất thường xảy ra: nếu biểu đồ luôn cần thiết, và nếu mất hơn 3.1 giây để tính toán tất cả các biểu đồ trong thử nghiệm này, thì trường hợp này với các trường được khởi tạo theo kiểu `lazy` sẽ thực sự làm giảm hiệu xuất. -Trong trường hợp này, tính toán biểu đồ không thuộc loại đó -- đó là một tính toán rất nhanh. Nói chung, có thể khó tìm thấy trường hợp tính toán lại một phần dữ liệu tốn chi phí hơn việc tuần tự hoá và giải mã dữ liệu đó. Nhưng nó là một cái gì đó để cân nhắc như mã code tối ưu hoá. +Trong trường hợp này, tính toán biểu đồ không thuộc loại đó -- đó là một tính toán rất nhanh. Nói chung, có thể khó tìm thấy trường hợp tính toán lại một phần dữ liệu tốn chi phí hơn việc `serialization` và `deserialization` dữ liệu đó. Nhưng nó là một cái gì đó để cân nhắc như mã code tối ưu hoá. -Thử nghiệm này không thực sự truyền dữ liệu; dữ liệu được ghi vào và đọc ra từ các mảng byte được gán sẵn, đo đó nó chỉ đo thời gian cho tuần tự hoá và giải mã. Tuy nhiên, hãy lưu ý rằng việc tạo trường biểu đồ tạm thời cũng đã tiết kiệm được khoảng 13% kích thước dữ liệu. Điều đó khá quan trọng nếu dữ liệu được truyền qua mạng. +Thử nghiệm này không thực sự truyền dữ liệu; dữ liệu được ghi vào và đọc ra từ các mảng byte được gán sẵn, đo đó nó chỉ đo thời gian cho `serialization` và `deserialization`. Tuy nhiên, hãy lưu ý rằng việc tạo trường biểu đồ là `transient` cũng đã tiết kiệm được khoảng 13% kích thước dữ liệu. Điều đó khá quan trọng nếu dữ liệu được truyền qua mạng. -### Nén dữ liệu đã được tuần tự hoá -Điều này dẫn đến cách thứ 3 mà hiệu suất tuần tự hoá của mã code có thể được cải thiện: nén dữ liệu tuần tự hoá để truyền nhanh hơn qua mạng chậm. Trong lớp lịch sử hàng tồn kho, nó được thực hiện bằng cách nén bản đồ giá trong quá trình tuần tự hoá: +### Nén dữ liệu đã được serialization +Điều này dẫn đến cách thứ 3 mà hiệu suất `serialization` của mã code có thể được cải thiện: nén dữ liệu `serialization` để truyền nhanh hơn qua mạng chậm. Trong lớp lịch sử hàng tồn kho, nó được thực hiện bằng cách nén bản đồ giá trong quá trình `serialization`: ```java public class StockPriceHistoryCompress implements StockPriceHistory, Serializable { private byte[] zippedPrices; @@ -163,41 +163,41 @@ public class StockPriceHistoryCompress implements StockPriceHistory, Serializabl } } ``` -Phương thức `makeZippedPrices()` tuần tự hoá bàn đồ giá thành mảng byte và lưu các byte kết quả, sau đó tuần tự hoá bình thường trong phương thức `writeObject()` khi nó gọi phương thức `defaultWriteObject()`. (Trên thực tế, miễn là quá trình tuần tự hoá đang được tuỳ chỉnh, sẽ tốt hơn một chút nếu đánh dấu mảng `zippedPrices` là tạm thời và viết ra độ dài byte một các trực tiếp. Nhưng mã code này rõ ràng hơn, và đơn giản là tốt hơn) Trên quá trình giải mã, tính toán ngược lại được thực hiện. +Phương thức `makeZippedPrices()` `serialization` bàn đồ giá thành mảng byte và lưu các byte kết quả, sau đó `serialization` bình thường trong phương thức `writeObject()` khi nó gọi phương thức `defaultWriteObject()`. (Trên thực tế, miễn là quá trình `serialization` đang được tuỳ chỉnh, sẽ tốt hơn một chút nếu đánh dấu mảng `zippedPrices` là `transient` và viết ra độ dài byte một các trực tiếp. Nhưng mã code này rõ ràng hơn, và đơn giản là tốt hơn) Trên quá trình `deserialization`, tính toán ngược lại được thực hiện. -Nếu mục tiêu là tuần tự hoá thành một mảng byte (như trong mã mẫu ban đầu), thì đây là một mệnh đề thất bại. Điều đó không có gì đáng ngạc nhiên; thời gian cần thiết để nén các byte lâu hơn nhiều so với thời gian ghi chúng vào một mảng byte cục bộ. Thời gian được thể hiện trong bảng 2. +Nếu mục tiêu là `serialization` thành một mảng byte (như trong mã mẫu ban đầu), thì đây là một thất bại. Điều này không có gì đáng ngạc nhiên; thời gian cần thiết để nén các byte lâu hơn nhiều so với thời gian ghi chúng vào một mảng byte cục bộ. Thời gian được thể hiện trong bảng 2. -Bảng 2: Thời gian tuần tự hoá và giải mã 10,000 đối tượng với nén +Bảng 2: Thời gian serialization và deserialization 10,000 đối tượng với nén ![Bảng 2](/assets/images/posts/2022-10-25/serialization-3.png) -Điểm thú vị nhất về bảng này là dòng cuối cùng. Trong thử ngiệm đó, dữ liệu được nén trước khi gửi, nhưng phương thức `unzipPrices()` không gọi phương thức `readObject()`. Thay vào đó, nó được gọi khi cần thiết, đó là lần đâu tiên khách hàng gọi phương thức `getPrice()`. Không có gọi lệnh đó, chỉ có một số đối tượng BigDecimal được giải mã, khá nhanh. +Điểm thú vị nhất về bảng này là dòng cuối cùng. Trong thử ngiệm đó, dữ liệu được nén trước khi gửi, nhưng phương thức `unzipPrices()` không gọi phương thức `readObject()`. Thay vào đó, nó được gọi khi cần thiết, đó là lần đâu tiên `client` gọi phương thức `getPrice()`. Không gọi lệnh đó, chỉ có một số đối tượng `BigDecimal` được `deserialization`, khá nhanh. -Trong ví dụ này, rất có thể khách hàng sẽ không bao giờ cần giá trị thực tế: khách hàng chỉ cần gọi hàm getHightPrice() và các phương thức tương tự để truy xuất thông tin tổng hợp về dữ liệu. Miễn là những phương thức đó là tất cả những gì cần thiết, có thể tiết kiệm rất nhiều thời gian bằng cách giải nén thông tin giá một cách lười biếng. Giải nén lười biếng này cũng khá hưu ích nếu đối tượng được đề cập đang được duy trì (ví dụ: nếu đó là trang thái của phiên làm việc HTTP đang được lưu trữ dưới dạng bản sao trong trường hợp máy chủ bị lỗi). Giải nén một cách lười biếng giúp tiết kiệm thời gian của CPU (từ việc bỏ qua giải nén) và bộ nhớ (vì dữ liệu nén chiếm ít dung lượng hơn). +Trong ví dụ này, rất có thể `client` sẽ không bao giờ cần giá trị thực tế: khách hàng chỉ cần gọi hàm `getHightPrice()` và các phương thức tương tự để truy xuất thông tin tổng hợp về dữ liệu. Miễn là những phương thức đó là tất cả những gì cần thiết, có thể tiết kiệm rất nhiều thời gian bằng cách giải nén thông tin giá theo kiểu `lazy`. Giải nén `lazy` này cũng khá hưu ích nếu đối tượng được đề cập đang được duy trì (ví dụ: nếu đó là trang thái của HTTP session đang được lưu trữ dưới dạng bản sao trong trường hợp máy chủ bị lỗi). Giải nén theo kiểu `lazy` giúp tiết kiệm thời gian của CPU (từ việc bỏ qua giải nén) và bộ nhớ (vì dữ liệu nén chiếm ít dung lượng hơn). -Vì vậy, ngay cả khi ứng dụng được chạy ở mạng cục bộ, tốc độ cao - và rõ ràng nếu mục đích là tiết kiệm bộ nhớ hơn là thời gian - thì việc nén dữ liệu để tuần tự hoá và sau đó giải nén một cách lười biếng nó có thể khá hữu ích. +Vì vậy, ngay cả khi ứng dụng được chạy ở mạng cục bộ, tốc độ cao - và rõ ràng nếu mục đích là tiết kiệm bộ nhớ hơn là thời gian - thì việc nén dữ liệu để `serialization` và sau đó giải nén theo kiểu `lazy` nó có thể khá hữu ích. -Nếu mục đích của tuần tự hoá là để truyền dữ liệu qua mạng, thì nén sẽ giàng chiến thằng bất kỳ lúc nào có dữ liệu tiết kiệm. Bảng 3 thực hiện tuần tự hoá tương tự cho 10,000 đối tượng hàng tồn kho, nhưng lần này nó lại truyền dữ liệu qua một tiến trình khác. Tiến trình khác hoặc chạy trên cùng 1 máy, hoặc trên một máy được truy cập thông qua kết nối băng thông rộng của tôi. +Nếu mục đích của `serialization` là để truyền dữ liệu qua mạng, thì nén sẽ giàng chiến thằng bất kỳ lúc nào. Bảng 3 thực hiện `serialization` tương tự cho 10,000 đối tượng hàng tồn kho, nhưng lần này nó lại truyền dữ liệu qua một tiến trình khác. Tiến trình khác hoặc chạy trên cùng 1 máy, hoặc trên một máy được truy cập thông qua kết nối băng thông rộng của tôi. Bảng 3: Thời gian truyền tải 10,000 đồi tượng qua mạng ![Bảng 3](/assets/images/posts/2022-10-25/serialization-3.png) -Giao tiếp mạng nhanh nhất là giao tiếp giữa 2 tiến trình trên cùng 1 máy - giao tiếp đó hoàn toàn không đi qua mạng, mặc dù nó gửi dữ liệu thông qua giao diện của hệ điều hành. Ngay cả trong trường hợp đó, việc nén dữ liệu và giải nén dữ liệu một cách lười biếng đã dần đạt tới hiệu quả nhanh nhất (ít nhất đối với thử nghiệm này). Và thứ tự chênh lệch về độ lớn trong lượng dữ liệu đã tạo ra khác biệt lớn (có thể dự đoán được) trong tổng thời gian khi một mạng chậm hơn tham gia. +Giao tiếp mạng nhanh nhất là giao tiếp giữa 2 tiến trình trên cùng 1 máy - giao tiếp đó hoàn toàn không đi qua mạng, mặc dù nó gửi dữ liệu thông qua giao diện của hệ điều hành. Ngay cả trong trường hợp đó, việc nén dữ liệu và giải nén dữ liệu theo kiểu `lazy` đã dần đạt tới hiệu quả nhanh nhất (ít nhất đối với thử nghiệm này). Và thứ tự chênh lệch về độ lớn trong lượng dữ liệu đã tạo ra khác biệt lớn (có thể dự đoán được) trong tổng thời gian khi có sự tham gia của mảng chậm hơn. ### Theo dõi các đối tượng trùng lặp -Phần này bắt đầu với một ví dụ về cách không tuần tự hoá dữ liệu có chứa các tham chiếu dữ liệu, để tránh các tham chiếu đối tượng bị xâm phạm khi dữ liệu được giải mã. Tuy nhiên, một trong nhưng cách tối ưu hoá manh mẽ hơn có thể có trong phương thức `writeObject()` là không viết ra các tham chiếu đối tượng trùng lặp. Trong trường hợp của lớp `StockPriceHistoryImpl`, điều đó có nghĩa là không viết ra các tham chiếu trùng lặp của bàn đồ giá. Bời vì ví dụ sử dụng một lớp JDK tiêu chuẩn cho bản đồ đó, chúng ta không cần lo lắng về điều đó: các lớp JDK đã được viết để tuần tự hoá một các tối ưu. Tuy nhiên, cần xem xét các lớp đó thực hiện tối ưu hoá như thế nào để hiểu điều gì có thể xảy ra. +Phần này bắt đầu với một ví dụ về cách không `serialization` dữ liệu có chứa các tham chiếu dữ liệu, để tránh các tham chiếu đối tượng bị xâm phạm khi dữ liệu được `deserialization`. Tuy nhiên, một trong nhưng cách tối ưu hoá manh mẽ hơn có thể có trong phương thức `writeObject()` là không viết ra các tham chiếu đối tượng trùng lặp. Trong trường hợp của lớp `StockPriceHistoryImpl`, điều đó có nghĩa là không viết ra các tham chiếu trùng lặp của bàn đồ giá. Bời vì ví dụ sử dụng một lớp JDK tiêu chuẩn cho bản đồ đó, chúng ta không cần lo lắng về điều đó: các lớp JDK đã được viết để `serialization` một các tối ưu. Tuy nhiên, cần xem xét các lớp đó thực hiện tối ưu hoá như thế nào để hiểu điều gì có thể xảy ra. -Trong lớp `StockPriceHistoryImpl`, cấu trúc khoá là một sơ đồ cây. Một phiên bản đơn giản của bản đồ đó xuất hiện trong hình 1 với tuần tự hoá mặc định, JVM sẽ ghi ra các trường dữ liệu ban đầu cho node A; thì nó sẽ gọi đệ quy phương thức `writeObject()` cho node B (và sau đó cho node C). Mã code cho node B có thể viết ra trường dữ liệu ban đầu của nó, và sau đó đệ quy viết ra dữ liệu cho trường cha của nó. +Trong lớp `StockPriceHistoryImpl`, cấu trúc khoá là một sơ đồ cây. Một phiên bản đơn giản của bản đồ đó xuất hiện trong hình 1 với `serialization` mặc định, JVM sẽ ghi ra các trường dữ liệu ban đầu cho node A; thì nó sẽ gọi đệ quy phương thức `writeObject()` cho node B (và sau đó cho node C). Mã code cho node B có thể viết ra trường dữ liệu ban đầu của nó, và sau đó đệ quy viết ra dữ liệu cho trường cha của nó. -Nhưng chờ một chút - trường cha đó là node A, đã được viết. Mã tuần tự hoá đối tượng đủ thông minh để nhận ra rằng: nó không viết lại dữ liệu cho node A. Thay vào đó, nó chỉ thêm một tham chiếu đối tượng và dữ liệu đã được ghi trước đó. +Nhưng chờ một chút - trường cha đó là node A, đã được viết. Mã `serialization` đối tượng đủ thông minh để nhận ra rằng: nó không viết lại dữ liệu cho node A. Thay vào đó, nó chỉ thêm một tham chiếu đối tượng và dữ liệu đã được ghi trước đó. -Theo dõi tập hợp các đối tượng viết trước đó, cũng như tất cả các đệ quy đó, sẽ thêm một hiệu xuất nhỏ vào tuần tự hoá đối tượng. Tuy nhiên, như được minh hoạ trong ví dụ vói một mảng của đối tượng điểm, nó không thể tránh được điều này: mã code phải theo dõi đối tượng viết ra trước đó và tạo lại các tham chiếu đối tượng chính xác. Tuy nhiên, có thể thực hiện tối ưu hoá thông minh bằng cách loại bỏ các tham chiếu đối tượng có thể dễ dàng tạo lại khi đối tượng được giải mã. +Theo dõi tập hợp các đối tượng viết trước đó, cũng như tất cả các đệ quy đó, sẽ thêm một hiệu xuất nhỏ vào `serialization` đối tượng. Tuy nhiên, như được minh hoạ trong ví dụ với một mảng của đối tượng điểm, nó không thể tránh được điều này: mã code phải theo dõi đối tượng viết ra trước đó và tạo lại các tham chiếu đối tượng chính xác. Tuy nhiên, có thể thực hiện tối ưu hoá thông minh bằng cách loại bỏ các tham chiếu đối tượng có thể dễ dàng tạo lại khi đối tượng được `deserialization`. Hình 1: Cấu trúc sơ đồ cây đơn giản ![Hình 1](/assets/images/posts/2022-10-25/serialization-f-1.png) -Các bộ sưu tập khác nhau xử lý điều này theo cách khác nhau. Ví dụ, lớp TreeMap chỉ đơn giản lặp qua cây và chỉ ghi lại các khoá và giá trị; tuần tự hoá loại bỏ tất cả các thông tin về mối quan hệ giữa các khoá (tức là thứ tự sắp xếp của chúng). Khi dữ liệu đã được giải mã, phương thức `readObject()` sẽ sắp xếp lại dữ liệu để tạo ra một cây. Mặc dù sắp xếp lại đối tượng nghe có vẻ tốn kém, nhưng không phải vậy: quá trình đó nhanh hơn khoảng 20% trên một tập hợp 10,000 đối tượng hàng tồn kho so với việc sử dụng tuần tự hoá mặc định, theo đuổi tất cả các tham chiếu đối tượng. +Các bộ sưu tập khác nhau xử lý điều này theo cách khác nhau. Ví dụ, lớp `TreeMap` chỉ đơn giản lặp qua cây và chỉ ghi lại các khoá và giá trị; `serialization` loại bỏ tất cả các thông tin về mối quan hệ giữa các khoá (tức là thứ tự sắp xếp của chúng). Khi dữ liệu đã được `deserialization`, phương thức `readObject()` sẽ sắp xếp lại dữ liệu để tạo ra một cây. Mặc dù sắp xếp lại đối tượng nghe có vẻ tốn kém, nhưng không phải vậy: quá trình đó nhanh hơn khoảng 20% trên một tập hợp 10,000 đối tượng hàng tồn kho so với việc sử dụng `serialization` mặc định, theo đuổi tất cả các tham chiếu đối tượng. -Lớp TreeMap cũng được hưởng lợi từ việc tối ưu hoá bời vì nó có thể viết ra ít đối tượng hơn. Một node (hoặc trong ngôn ngữ JDK, một Entry) trong bản đồ chứa 2 đối tượng: khoá và giá trị. Bởi vì bản đồ không thể chứa 2 node giống nhau, mã code tuần tự hoá không cần lo lắng về việc bảo toàn các tham chiếu đối tượng đến các node. Trong trường hợp này, nó có thể bỏ qua việc viết đối tượng node chính nó, và đơn giảm chỉ ghi trực tiếp các đối tượng khoá và giá trị. Vì vậy, phương thức `writeObject()` trông giống như thế này (cú pháp điều chỉnh cho dễ đọc): +Lớp TreeMap cũng được hưởng lợi từ việc tối ưu hoá bời vì nó có thể viết ra ít đối tượng hơn. Một node (hoặc trong ngôn ngữ JDK, một Entry) trong bản đồ chứa 2 đối tượng: khoá và giá trị. Bởi vì bản đồ không thể chứa 2 node giống nhau, mã code `serialization` không cần lo lắng về việc bảo toàn các tham chiếu đối tượng đến các node. Trong trường hợp này, nó có thể bỏ qua việc viết đối tượng node chính nó, và đơn giảm chỉ ghi trực tiếp các đối tượng khoá và giá trị. Vì vậy, phương thức `writeObject()` trông giống như thế này (cú pháp điều chỉnh cho dễ đọc): ```java private void writeObject(ObjectOutputStream oos) throws IOException { .... @@ -210,20 +210,20 @@ private void writeObject(ObjectOutputStream oos) throws IOException { ``` Điều này trông rất giống với mã code không hoạt động cho ví dụ Point. Sự khác biệt trong trường hợp này là mã code vẫn đang viết các đối tượng trong đó các đối tượng đó có thể giống nhau. Bản đồ cây không thể có 2 node giống nhau, vì vậy không cần phải viết ra node tham chiếu. Bản đồ cây có thể có 2 giá trị giống nhau, vì vậy các giá trị phải được viết dưới dạng tham chiếu đối tượng. -Điều này mang lại cho chúng ta một vòng tròn đầy đủ: như tôi đã nêu ở đầu phần này, việc tối ưu hoá đối tượng tuần tự hoá chính xác có thể rất khó. Nhưng khi tuần tự hoá đối tượng là một nút thắt cổ chai đáng kể trong ứng dụng, việc tối ưu hoá chúng 1 cách chính xác có thể mang lại lợi ích quan trọng. +Điều này mang lại cho chúng ta một vòng tròn đầy đủ: như tôi đã nêu ở đầu phần này, việc tối ưu hoá đối tượng `serialization` chính xác có thể rất khó. Nhưng khi `serialization` đối tượng là một nút thắt cổ chai đáng kể trong ứng dụng, việc tối ưu hoá chúng 1 cách chính xác có thể mang lại lợi ích quan trọng. ### Điều gì về Externalizable? -Phần này chưa nói về một cách tiếp cận khác để tối ưu tuần tự hoá đối tượng, đó là triển khai giao diện Externalizable chứ không phải là giao diện Serializable. +Phần này chưa nói về một cách tiếp cận khác để tối ưu `serialization` đối tượng, đó là triển khai giao diện `Externalizable` chứ không phải là giao diện `Serializable`. -Sự khác biệt thực tế giữa 2 giao diện này là chúng xử lý các trường được đánh dấu là tạm thời. Giao diện Serializable viết ra các trường không được đánh dấu khi phương thức `writeObject()` gọi phương thức `defaultWriteObject()`. Giao diện Externalizable không có phương thức như vậy. Lớp Externalizable phải viết rõ ràng ra tất cả các trường, tạm thơi hoặc không, mà nó quan tâm đến trong khi truyền. +Sự khác biệt thực tế giữa 2 giao diện này là chúng xử lý các trường được đánh dấu là `transient`. Giao diện `Serializable` viết ra các trường không được đánh dấu khi phương thức `writeObject()` gọi phương thức `defaultWriteObject()`. Giao diện `Externalizable` không có phương thức như vậy. Lớp `Externalizable` phải viết rõ ràng ra tất cả các trường, `transient` hoặc không, mà nó quan tâm đến trong khi truyền. -Nếu như tất cả các trường trong đối tượng là tạm thời, tốt hơn là nên trên khai giao diện Serializable và gọi phương thức `defaultWriteObject()`. Điều đó dẫn đến mã code dễ bảo trì hơn nhiều khi các đối tượng được thêm vào (và xoá khỏi) mã code. Và không có lợi ích cố hưu nào đối với giao diện Externalizable từ quan điểm hiệu xuất: cuối cùng, điều quan trọng là số lượng dữ liệu được ghi. +Nếu như tất cả các trường trong đối tượng là `transient`, tốt hơn là nên trên khai giao diện `Serializable` và gọi phương thức `defaultWriteObject()`. Điều đó dẫn đến mã code dễ bảo trì hơn nhiều khi có các trường được thêm vào (hoặc xoá đi). Và không có lợi ích nào đối với giao diện `Externalizable` từ quan điểm hiệu xuất: cuối cùng, điều quan trọng vẫn là số lượng dữ liệu được ghi. ### Tóm tắt nhanh -1. Tuần tự hoá dữ liệu, đặc biệt trong Java EE, có thể là một điểm nghẽn hiệu xuất lớn -2. Đánh dấu các biến là tạm thời sẽ giúp tuần tự hoá nhanh hơn và giảm lượng dữ liệu được truyền tải. Cả 2 điều đó thường là những chiến thắng hiệu xuất lớn, trừ khi việc tạo lại dữ liệu trên nơi nhận mất một thời gian rất dài. -3. Các tối ưu khác thông qua phương thức `writeObject()` và `readObject()` có thể tăng tốc tuần tự hoá một cách đáng kể. Tiếp cận chúng một cách thận trong, vì rất dễ mắc lỗi và tạo ra một lỗi khó phát hiện. -4. Nén dữ liệu tuần tự hoá thường có lợi, ngay cả khi dữ liệu không truyền qua mạng chậm +1. `serialization` dữ liệu, đặc biệt trong Java EE, có thể là một điểm nghẽn hiệu xuất lớn +2. Đánh dấu các biến là `transient` sẽ giúp `serialization` nhanh hơn và giảm lượng dữ liệu được truyền tải. Cả 2 điều đó thường là những chiến thắng hiệu xuất lớn, trừ khi việc tạo lại dữ liệu ở nơi nhận mất một thời gian rất dài. +3. Các tối ưu khác thông qua phương thức `writeObject()` và `readObject()` có thể tăng tốc `serialization` một cách đáng kể. Tiếp cận chúng một cách thận trong, vì rất dễ mắc lỗi và tạo ra một lỗi khó phát hiện. +4. Nén dữ liệu `serialization` thường có lợi, ngay cả khi dữ liệu không truyền qua mạng chậm ## Refs: 1. Sách Java Performance - The Definitive Guide