a. Làm thế nào để tốc độ của Java ngày nay so với C ++?
Khó đo lường. Điều đáng chú ý là một phần chính của tốc độ thực hiện, đó là cấp phát bộ nhớ, là các thuật toán rất khác nhau trong Java và C ++. Bản chất không xác định của trình thu thập khiến cho việc thu thập dữ liệu hiệu suất có ý nghĩa rất khó so với quản lý bộ nhớ xác định của C ++, bởi vì bạn không bao giờ có thể chắc chắn trạng thái của trình thu thập đó là gì. điều đó có thể có ý nghĩa so sánh chúng. Một số mẫu cấp phát bộ nhớ chạy nhanh hơn nhiều với một GC, một số mẫu chạy nhanh hơn nhiều với bộ cấp phát riêng.
Tuy nhiên, điều tôi muốn nói là Java GC phải chạy nhanh trong mọi tình huống. Tuy nhiên, một công cụ phân bổ riêng có thể được hoán đổi cho một công cụ phù hợp hơn. Gần đây tôi đã đưa ra một câu hỏi trên SO về lý do tại sao một C # Dictionary
có thể thực thi trong (0,45 ms trên máy của tôi) so với tương đươngstd::unordered_map
mà thực hiện trên (10ms trên máy của tôi). Tuy nhiên, chỉ bằng cách hoán đổi bộ cấp phát và tìm kiếm những thứ thích hợp hơn, tôi đã cắt thời gian thực hiện đó xuống còn 0,34ms trên máy của mình - một phần ba của thời gian chạy ban đầu. Bạn không bao giờ có thể hy vọng thực hiện loại tối ưu hóa tùy chỉnh đó với Java. Một ví dụ tuyệt vời về nơi điều này có thể tạo ra sự khác biệt thực sự là phân luồng. Các thư viện luồng gốc như TBB cung cấp các bộ cấp phát bộ đệm luồng nhanh hơn so với các bộ cấp phát truyền thống khi xử lý nhiều phân bổ trên nhiều luồng.
Bây giờ, nhiều người sẽ nói về các cải tiến JIT và cách JIT có nhiều thông tin hơn. Chắc chắn, đó là sự thật. Nhưng nó thậm chí còn không gần với những gì trình biên dịch C ++ có thể kéo - bởi vì trình biên dịch có thời gian và không gian vô hạn để chạy, theo quan điểm về thời gian chạy của chương trình cuối cùng. Mỗi chu kỳ và mỗi byte mà JIT dành để suy nghĩ về cách tốt nhất để tối ưu hóa chương trình của bạn là một chu trình mà chương trình của bạn không chi tiêu thực hiện và không thể sử dụng cho nhu cầu bộ nhớ của chính nó.
Ngoài ra, sẽ luôn có những lúc tối ưu hóa trình biên dịch và JIT không thể chứng minh các tối ưu hóa nhất định - đặc biệt là trong trường hợp những thứ như phân tích thoát. Trong C ++, sau đó là các giá trị là trên stack nào , trình biên dịch không cần phải thực hiện nó. Ngoài ra, có những điều đơn giản, như bộ nhớ liền kề. Nếu bạn phân bổ một mảng trong C ++, thì bạn phân bổ một mảng duy nhất, liền kề. Nếu bạn phân bổ một mảng trong Java, thì nó không liền kề nhau, bởi vì mảng chỉ chứa đầy các con trỏ có thể trỏ đến bất cứ đâu. Đây không chỉ là chi phí bộ nhớ và thời gian cho các lần chuyển hướng kép mà còn cả chi phí bộ nhớ cache. Kiểu này là ở chỗ ngữ nghĩa ngôn ngữ của Java đơn giản thực thi rằng nó phải chậm hơn mã C ++ tương đương.
Cuối cùng, kinh nghiệm cá nhân của tôi là Java có thể trung bình bằng một nửa tốc độ của C ++. Tuy nhiên, thực tế không có cách nào để sao lưu bất kỳ báo cáo hiệu suất nào mà không có bộ điểm chuẩn cực kỳ toàn diện, vì các thuật toán cơ bản khác nhau có liên quan.
b. Có thể tạo một tiêu đề AAA hiện đại bằng Java không?
Tôi cho rằng bạn có nghĩa là "trò chơi", ở đây, và không phải là một cơ hội. Đầu tiên, bạn phải tự viết mọi thứ từ gần như tất cả các thư viện và cơ sở hạ tầng hiện có nhắm mục tiêu C ++. Mặc dù không làm cho nó không thể thực hiện được, nó chắc chắn có thể đóng góp vững chắc cho những điều không khả thi. Thứ hai, ngay cả các công cụ C ++ cũng khó có thể phù hợp với các hạn chế bộ nhớ nhỏ của các bảng điều khiển hiện có - nếu các JVM thậm chí còn tồn tại cho các máy chơi game đó và các game thủ PC mong đợi nhiều hơn một chút cho bộ nhớ của chúng. Tạo các trò chơi AAA hiệu suất là đủ khó trong C ++, tôi không thấy làm thế nào nó có thể đạt được trong Java. Không ai từng viết một trò chơi AAA với thời gian đáng kể dành cho một ngôn ngữ không được biên dịch. Hơn thế nữa, nó chỉ đơn giản là cực kỳ dễ bị lỗi. Sự phá hủy mang tính quyết định là điều cần thiết khi xử lý, ví dụ, tài nguyên GPU - và trong Java, bạn '
c. Trong những lĩnh vực cụ thể là Java chậm hơn C ++, nếu có? (ví dụ: Số giòn, đồ họa hoặc chỉ xung quanh)
Tôi chắc chắn sẽ đi khắp nơi. Bản chất tham chiếu được thi hành của tất cả các đối tượng Java có nghĩa là Java có nhiều hướng dẫn và tham chiếu trong đó hơn C ++ - một ví dụ tôi đã đưa ra trước đó với các mảng, nhưng cũng áp dụng cho tất cả các đối tượng thành viên. Trong đó trình biên dịch C ++ có thể tra cứu biến thành viên trong thời gian không đổi, thời gian chạy Java phải theo một con trỏ khác. Bạn càng truy cập nhiều, điều này sẽ càng chậm, và JIT không thể làm gì về điều đó.
Trong đó C ++ có thể giải phóng và sử dụng lại một phần bộ nhớ gần như ngay lập tức, trong Java bạn phải chờ bộ sưu tập và tôi hy vọng rằng phần đó không bị hết bộ nhớ cache và vốn đã yêu cầu nhiều bộ nhớ hơn đồng nghĩa với hiệu năng phân trang và bộ nhớ đệm thấp hơn. Sau đó nhìn vào ngữ nghĩa cho những thứ như đấm bốc và unboxing. Trong Java, nếu bạn muốn tham chiếu một int, bạn phải tự động phân bổ nó. Đó là một sự lãng phí vốn có so với ngữ nghĩa C ++.
Sau đó, bạn có vấn đề chung. Trong Java, bạn chỉ có thể hoạt động trên các đối tượng chung thông qua kế thừa thời gian chạy. Trong C ++, các mẫu có nghĩa đen bằng không - một thứ Java không thể phù hợp. Điều này có nghĩa là tất cả các mã chung trong Java vốn đã chậm hơn một mã tương đương chung trong C ++.
Và sau đó bạn đến với Hành vi không xác định. Mọi người đều ghét nó khi chương trình của họ trưng bày UB và mọi người đều ước rằng nó không tồn tại. Tuy nhiên, UB về cơ bản cho phép tối ưu hóa không bao giờ tồn tại trong Java. Hãy xem bài viết này mô tả tối ưu hóa dựa trên UB. Không xác định hành vi có nghĩa là việc triển khai có thể thực hiện tối ưu hóa nhiều hơn và giảm mã cần thiết để kiểm tra các điều kiện sẽ không được xác định trong C ++ nhưng được xác định trong Java.
Về cơ bản, ngữ nghĩa của Java cho rằng đó là ngôn ngữ chậm hơn C ++.
Bây giờ Java có được coi là ngôn ngữ được biên dịch hay ngôn ngữ được dịch không?
Nó không thực sự phù hợp với một trong những nhóm đó. Tôi nói rằng quản lý thực sự là một danh mục riêng biệt, mặc dù tôi nói rằng nó chắc chắn giống một ngôn ngữ được giải thích hơn là một ngôn ngữ được biên dịch. Quan trọng hơn, có khá nhiều chỉ có hai hệ thống được quản lý chính là JVM và CLR và khi bạn nói "được quản lý" thì điều đó đủ rõ ràng.
Một số thiếu sót lớn của Java đã được giải quyết từ những ngày đầu là gì?
Tự động đấm bốc và unboxing là điều duy nhất tôi biết. Các khái quát giải quyết một số vấn đề, nhưng xa từ nhiều.
Một số thiếu sót lớn của Java vẫn chưa được giải quyết là gì?
Tướng của họ rất, rất yếu Tổng quát của C # mạnh hơn đáng kể - mặc dù tất nhiên, cả hai đều không phải là mẫu khá. Phá hủy quyết định là một thiếu lớn. Bất kỳ hình thức lambda / đóng cửa nào cũng là một vấn đề lớn - bạn có thể quên API chức năng trong Java. Và, tất nhiên, luôn có vấn đề về hiệu suất, đối với những lĩnh vực cần chúng.