LinkedList có nhanh hơn không? Tôi có nên hoán đổi `cho mỗi` bằng` iterator` không? `ArrayList` này có nên là `Array` không? Bài viết này ra đời nhằm đáp lại một sự tối ưu hóa ác độc đến mức nó đã vĩnh viễn khắc sâu vào trí nhớ của tôi. Trước khi bắt đầu tìm hiểu Java và các cách giải quyết sự can thiệp, từ trình thu thập rác hoặc từ chuyển đổi ngữ cảnh, trước tiên chúng ta hãy xem qua các nguyên tắc cơ bản về viết mã cho tương lai của bạn. Tối ưu hóa sớm là gốc rễ của mọi tội lỗi. Bạn đã từng nghe nó trước đây; tối ưu hóa sớm là gốc rễ của mọi tội lỗi. Cũng đôi khi. Khi viết phần mềm, tôi có niềm tin vững chắc vào việc: mang ; bạn nên cố gắng thuật lại ý định như thể bạn đang viết một câu chuyện. tính mô tả nhất có thể ; điều đó có nghĩa là bạn nên biết các nguyên tắc cơ bản của ngôn ngữ và áp dụng chúng cho phù hợp. tối ưu nhất có thể Càng mô tả càng tốt Mã của bạn phải nói lên ý định và phần lớn liên quan đến cách bạn đặt tên cho các phương thức và biến. int[10] array1; // bad int[10] numItems; // better int[10] backPackItems; // great Chỉ cần nhìn vào tên biến là bạn đã có thể suy ra chức năng. Trong khi là trừu tượng, cho bạn biết rất nhiều về hành vi dự kiến. numItems backPackItems Hoặc nói rằng bạn có phương pháp này: List<Countries> visitedCountries() { if(noCountryVisitedYet) return new ArrayList<>(0); } // (...) return listOfVisitedCountries; } Theo như mã, điều này có vẻ ít nhiều ổn. Chúng ta có thể làm tốt hơn không? Chúng tôi chắc chắn có thể! List<Countries> visitedCountries() { if(noCountryVisitedYet) return Collections.emptyList(); } // (...) return listOfVisitedCountries; } Đọc mang tính mô tả nhiều hơn Collections.emptyList() new ArrayList<>(0); Hãy tưởng tượng bạn đang đọc đoạn mã trên lần đầu tiên và tình cờ gặp mệnh để kiểm tra xem người dùng đã thực sự đến thăm các quốc gia hay chưa. Ngoài ra, hãy tưởng tượng điều này được chôn trong một lớp học dài, đọc chắc chắn mang tính mô tả nhiều hơn , bạn cũng đảm bảo rằng nó không thể thay đổi, đảm bảo mã máy khách không thể sửa đổi nó. đề bảo vệ Collections.emptyList() new ArrayList<>(0) Tối ưu nhất có thể Biết ngôn ngữ của bạn và sử dụng nó cho phù hợp. Nếu bạn cần , không cần phải bọc nó trong đối tượng . Điều tương tự cũng xảy ra với việc sử dụng nếu tất cả những gì bạn thực sự cần là . double Double List Array Biết rằng bạn nên nối các Chuỗi bằng hoặc nếu bạn đang chia sẻ trạng thái giữa các luồng: StringBuilder StringBuffer // don't do this String votesByCounty = ""; for (County county : counties) { votesByCounty += county.toString(); } // do this instead StringBuilder votesByCounty = new StringBuilder(); for (County county : counties) { votesByCounty.append(county.toString()); } Biết cách lập chỉ mục cơ sở dữ liệu của bạn. Dự đoán tắc nghẽn và bộ nhớ đệm phù hợp. Tất cả những điều trên là tối ưu hóa. Chúng là loại tối ưu hóa mà bạn nên biết và thực hiện với tư cách là những công dân đầu tiên. Làm thế nào để bạn giết nó đầu tiên? Tôi sẽ không bao giờ quên một bản hack mà tôi đã đọc cách đây vài năm. Sự thật mà nói, tác giả đã nhanh chóng quay lại, nhưng nó cho thấy rất nhiều điều xấu xa có thể xuất phát từ những ý định tốt. // do not do this, ever! int i = 0; while (i<10000000) { // business logic if (i % 3000 == 0) { //prevent long gc try { Thread.sleep(0); } catch (Ignored e) { } } } Một công cụ thu gom rác từ địa ngục! Bạn có thể đọc thêm về lý do và cách thức hoạt động của đoạn mã trên . Mặc dù cách khai thác chắc chắn rất thú vị nhưng đây là một trong những điều bạn nên làm. trong bài viết gốc không bao giờ Hoạt động theo tác dụng phụ, không có mục đích gì trong khối này Thread.sleep(0) Hoạt động bằng cách khai thác sự thiếu hụt mã ở hạ lưu Đối với bất kỳ ai kế thừa mã này, nó thật tối nghĩa và kỳ diệu Chỉ bắt đầu rèn thứ gì đó phức tạp hơn một chút nếu sau khi viết với tất cả các , bạn gặp phải nút thắt cổ chai. Nhưng hãy tránh xa những cách pha chế như trên. tối ưu hóa mặc định mà ngôn ngữ cung cấp Làm thế nào để giải quyết vấn đề thu gom rác ? đó Nếu sau khi mọi việc đã xong, Bộ thu gom rác vẫn là bộ phận gây phản kháng, thì đây là một số cách bạn có thể thử: Nếu dịch vụ của bạn nhạy cảm với độ trễ đến mức bạn không thể cho phép GC, hãy chạy với . "Epsilon GC" và tránh hoàn toàn GC -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC Điều này rõ ràng sẽ tăng bộ nhớ của bạn cho đến khi bạn gặp ngoại lệ OOM, do đó, đó là một kịch bản ngắn hạn hoặc chương trình của bạn được tối ưu hóa để không tạo đối tượng Nếu dịch vụ của bạn hơi nhạy cảm với độ trễ, nhưng , hãy chạy GC1 và cung cấp cho nó nội dung như (mặc định là 250 mili giây) dung sai cho phép cho phép mất một chút thời gian -XX:MaxGCPauseTimeMillis=100 , chẳng hạn như một trong số chúng gọi hoặc là các trình thu gom rác toàn cầu, bạn có thể ghi đè hành vi vi phạm bằng cách chạy với Nếu sự cố xuất phát từ các thư viện bên ngoài System.gc() Runtime.getRuntime().gc() -XX:+DisableExplicitGC Nếu bạn đang chạy trên JVM trên 11, hãy thử , những cải tiến về hiệu suất là rất lớn! . Bạn cũng có thể muốn kiểm tra này. Z Garbage Collector (ZGC) -XX:+UnlockExperimentalVMOptions -XX:+UseZGC điểm chuẩn JDK 21 GC PHIÊN BẢN BẮT ĐẦU PHIÊN BẢN KẾT THÚC GC MẶC ĐỊNH Java 1 Java 4 Máy thu gom rác nối tiếp Java 5 Java 8 Máy thu gom rác song song Java 9 đang diễn ra Máy thu gom rác G1 Lưu ý 1: kể từ Java 15, đã , nhưng bạn vẫn phải kích hoạt nó một cách rõ ràng bằng . ZGC sẵn sàng sản xuất -XX:+UseZGC Lưu ý 2: VM coi máy là lớp máy chủ nếu VM phát hiện nhiều hơn hai bộ xử lý và kích thước heap lớn hơn hoặc bằng 1792 MB. Nếu không phải lớp máy chủ, nó . sẽ mặc định là Serial GC Về bản chất, hãy chọn điều chỉnh GC khi rõ ràng rằng các hạn chế về hiệu suất của ứng dụng có liên quan trực tiếp đến hành vi thu gom rác và bạn có kiến thức chuyên môn cần thiết để thực hiện các điều chỉnh sáng suốt. Mặt khác, hãy tin tưởng vào cài đặt mặc định của JVM và tập trung vào việc tối ưu hóa mã cấp ứng dụng. - bạn sẽ muốn đọc u/shiphe bình luận đầy đủ Các thư viện liên quan khác mà bạn có thể muốn khám phá: Khai thác điểm chuẩn vi mô Java (JMH) Nếu bạn hóa cảm giác mà không có bất kỳ điểm chuẩn thực sự nào thì bạn đang tự làm hại chính mình. JMH là thư viện Java để kiểm tra hiệu suất thuật toán của bạn. Sử dụng nó. tối ưu trên thực tế Java-Thread-Affinity Ghim một tiến trình vào một lõi cụ thể có thể cải thiện số lần truy cập bộ đệm. Nó sẽ phụ thuộc vào phần cứng cơ bản và cách xử lý dữ liệu thường ngày của bạn. Tuy nhiên, thư viện này giúp việc triển khai trở nên dễ dàng đến mức nếu một phương pháp sử dụng nhiều CPU đang cản trở bạn, bạn sẽ muốn thử nghiệm nó. Bộ gây rối LMAX Đây là một trong những thư viện mà ngay cả khi bạn không cần nó, bạn vẫn muốn nghiên cứu. Ý tưởng là cho phép đồng thời có độ trễ cực thấp. Nhưng cách nó được triển khai, từ đến mang lại rất nhiều khái niệm mới. Tôi vẫn nhớ lần đầu tiên tôi phát hiện ra nó, bảy năm trước, tôi đã thức trắng đêm để tiêu hóa nó. sự đồng cảm cơ học bộ đệm vòng, Netflix jvmquake Tiền đề của là khi mọi thứ không ổn với JVM, bạn muốn nó chết và không bị treo. Một vài năm trước, tôi đã chạy mô phỏng trên cụm HTCondor có hạn chế về bộ nhớ và đôi khi, công việc sẽ bị kẹt do lỗi "hết bộ nhớ". jvmquake Thư viện này buộc JVM phải chết, cho phép bạn xử lý lỗi thực tế. Trong trường hợp cụ thể này, HTCondor sẽ tự động lên lịch lại công việc. suy nghĩ cuối cùng Mã khiến tôi viết bài này? Tôi đã viết tệ hơn nhiều. Tôi vẫn làm. Điều tốt nhất chúng ta có thể hy vọng là liên tục gây ra ít rắc rối hơn. Tôi hy vọng sẽ bất mãn khi nhìn vào mã của chính mình sau vài năm nữa. Và đó là một dấu hiệu tốt. Bạn có thể tìm thấy bài viết này và các bài viết khác tại Wasteofserver.com Chỉnh sửa & Cảm ơn bạn: gửi tới vì đã phát hiện ra lỗi có thể thay đổi trongvisitCountries và phần giải thích chi tiết. FlorianSchaetz visitedCountries() gửi tới và vì đã giải thích rằng , bạn sẽ nhận được Serial GC u/brunocborges u/BikingSquirrel trên các máy cấp thấp hơn cảm ơn vì đã dành thời gian giải thích rõ hơn khi nào bạn nên làm phiền GC và bạn/shiphe khi nào bạn không nên gửi tới vì đã đưa tôi đi đúng hướng về những gì bạn/tomwhoistrái ngược nên được coi là thông lệ tiêu chuẩn gửi tới (một lần nữa) vì đã cung cấp liên kết đến điểm chuẩn của bộ thu gom rác JDK 21 u/BikingSquirrel Cũng được xuất bản trên Wasteofserver.com