Điều gì chi phối "tốc độ" của ngôn ngữ lập trình?
Không có thứ gọi là "tốc độ" của ngôn ngữ lập trình. Chỉ có tốc độ của một chương trình cụ thể được viết bởi một progammer cụ thể được thực thi bởi một phiên bản cụ thể của một triển khai cụ thể của một công cụ thực thi cụ thể chạy trong một môi trường cụ thể.
Có thể có sự khác biệt lớn về hiệu năng khi chạy cùng một mã được viết bằng cùng một ngôn ngữ trên cùng một máy bằng cách sử dụng các triển khai khác nhau. Hoặc thậm chí sử dụng các phiên bản khác nhau của cùng một thực hiện. Ví dụ: chạy chuẩn ECMAScript chính xác trên cùng một máy chính xác bằng phiên bản SpiderMonkey từ 10 năm trước so với phiên bản từ năm nay có thể sẽ mang lại hiệu suất tăng bất cứ nơi nào giữa 2 × mật5 ×, thậm chí có thể là 10 ×. Điều đó có nghĩa là ECMAScript nhanh hơn 2 × so với ECMAScript, bởi vì chạy cùng một chương trình trên cùng một máy sẽ nhanh hơn 2 × với việc triển khai mới hơn? Điều đó không có ý nghĩa.
Điều này có liên quan gì đến quản lý bộ nhớ không?
Không hẳn vậy.
Lý do tại sao điều này xảy ra?
Tài nguyên. Tiền bạc. Microsoft có thể sử dụng nhiều người pha cà phê cho các lập trình viên biên dịch của họ hơn toàn bộ cộng đồng PHP, Ruby và Python kết hợp có những người làm việc trên máy ảo của họ.
Đối với nhiều hay ít bất kỳ tính năng nào của ngôn ngữ lập trình tác động đến hiệu suất theo một cách nào đó, đó cũng là một giải pháp. Ví dụ: C (Tôi đang sử dụng C ở đây để thay thế cho một lớp ngôn ngữ tương tự, một số ngôn ngữ thậm chí tồn tại trước C) không an toàn cho bộ nhớ, do đó nhiều chương trình C chạy cùng lúc có thể giẫm đạp ký ức của nhau. Vì vậy, chúng tôi phát minh ra bộ nhớ ảo và làm cho tất cả các chương trình C trải qua một lớp gián tiếp để chúng có thể giả vờ rằng chúng là những cái duy nhất chạy trên máy. Tuy nhiên, điều đó rất chậm và vì vậy, chúng tôi phát minh ra MMU và triển khai bộ nhớ ảo trong phần cứng để tăng tốc nó.
Nhưng! Ngôn ngữ an toàn bộ nhớ không cần tất cả điều đó! Có bộ nhớ ảo không giúp họ một chút. Trên thực tế, điều tồi tệ hơn: không chỉ bộ nhớ ảo không giúp các ngôn ngữ an toàn bộ nhớ, bộ nhớ ảo, ngay cả khi được triển khai trong phần cứng, vẫn ảnh hưởng đến hiệu suất. Nó có thể đặc biệt có hại đối với hiệu suất của các bộ thu gom rác (đây là số lượng đáng kể việc triển khai các ngôn ngữ an toàn bộ nhớ sử dụng).
Một ví dụ khác: CPU mục đích chung chính hiện đại sử dụng các thủ thuật tinh vi để giảm tần suất bỏ lỡ bộ đệm. Rất nhiều mánh khóe đó để cố gắng dự đoán mã nào sẽ được thực thi và bộ nhớ nào sẽ cần thiết trong tương lai. Tuy nhiên, đối với các ngôn ngữ có mức độ đa hình thời gian chạy cao (ví dụ: ngôn ngữ OO), thực sự rất khó để dự đoán các mẫu truy cập đó.
Nhưng, có một cách khác: tổng chi phí của bộ nhớ cache bị mất là số lần bỏ lỡ bộ nhớ cache nhân với chi phí của một bộ nhớ cache riêng lẻ. CPU chính thống cố gắng giảm số lần bỏ lỡ, nhưng nếu bạn có thể giảm chi phí cho một lần bỏ lỡ thì sao?
CPU Azul Vega-3 được thiết kế đặc biệt để chạy các JVM ảo hóa và nó có MMU rất mạnh với một số hướng dẫn chuyên biệt để giúp thu gom rác và phát hiện thoát (phân tích động tương đương với phân tích thoát tĩnh) và toàn bộ hệ thống vẫn có thể đạt được tiến bộ với hơn 20000 lỗi bộ nhớ cache nổi bật trong chuyến bay. Thật không may, giống như hầu hết các CPU dành riêng cho ngôn ngữ, thiết kế của nó chỉ đơn giản là bị chi tiêu và hết sức - bị ép buộc bởi "gã khổng lồ" Intel, AMD, IBM và những thứ tương tự.
Kiến trúc CPU chỉ là một ví dụ có tác động đến việc thực hiện ngôn ngữ có hiệu suất cao hay khó đến mức nào. Một ngôn ngữ như C, C ++, D, Rust phù hợp với mô hình lập trình CPU chính hiện đại sẽ dễ dàng thực hiện nhanh hơn ngôn ngữ phải "chiến đấu" và phá vỡ CPU, như Java, ECMAScript, Python, Ruby , PHP.
Thực sự, đó là tất cả một câu hỏi về tiền bạc. Nếu bạn chi số tiền bằng nhau để phát triển thuật toán hiệu năng cao trong ECMAScript, thì việc triển khai ECMAScript hiệu năng cao, một hệ điều hành hiệu năng cao được thiết kế cho ECMAScript, CPU hiệu suất cao được thiết kế cho ECMAScript đã được sử dụng trong lần trước hàng thập kỷ để làm cho các ngôn ngữ giống như C đi nhanh, sau đó bạn có thể sẽ thấy hiệu suất tương đương. Chỉ có điều, vào thời điểm này, người ta đã bỏ ra rất nhiều tiền để tạo ra các ngôn ngữ giống như C nhanh hơn là làm cho các ngôn ngữ giống như ECMAScript nhanh chóng, và các giả định của các ngôn ngữ giống như C được đưa vào toàn bộ từ MMU và CPU cho các hệ điều hành và hệ thống bộ nhớ ảo lên đến thư viện và khung.
Cá nhân tôi quen thuộc nhất với Ruby (thường được coi là "ngôn ngữ chậm"), vì vậy tôi sẽ đưa ra hai ví dụ: Hash
lớp (một trong những cấu trúc dữ liệu trung tâm trong Ruby, một từ điển giá trị khóa) trong Rubinius Việc triển khai Ruby được viết bằng Ruby nguyên chất 100% và nó có hiệu suất tương đương vớiHash
lớp trong YARV (triển khai được sử dụng rộng rãi nhất), được viết bằng C. Và có một thư viện xử lý hình ảnh được viết dưới dạng phần mở rộng C cho YARV, cũng có một "phiên bản dự phòng" thuần túy của Ruby để triển khai 'hỗ trợ C sử dụng rất nhiều thủ thuật Ruby rất năng động và phản xạ; một nhánh thử nghiệm của JRuby, sử dụng khung trình thông dịch Truffle AST và khung biên dịch Graal JIT của Oracle Labs, có thể thực thi phiên bản "dự phòng" thuần túy của Ruby nhanh như YARV có thể thực hiện phiên bản C được tối ưu hóa cao ban đầu. Điều này chỉ đơn giản là (tốt, bất cứ điều gì nhưng) đạt được bởi một số người thực sự thông minh thực hiện công cụ thực sự thông minh với tối ưu hóa thời gian chạy động, biên dịch JIT và đánh giá một phần.