2009-04-17 32 views
13

Điều gì gây khó khăn cho việc tăng tốc các ngôn ngữ được nhập động khi so sánh với các ngôn ngữ được nhập tĩnh. Nói cách khác, tài sản vốn có của các ngôn ngữ được nhập tĩnh là gì khiến chúng dễ dàng tối ưu hóa cho tốc độ thực thi?Tại sao các ngôn ngữ động được gõ chậm?

Trả lời

20

Khi truy cập thuộc tính/phương pháp bằng ngôn ngữ được nhập tĩnh, tra cứu thường có thể được giảm xuống địa chỉ hàm tĩnh. Ngay cả trong trường hợp của các phương pháp ảo, mà là chậm hơn, tra cứu chỉ là đọc một bù đắp từ một vtable.

Trong ngôn ngữ động, tên được dựa trên chuỗi. Muốn tìm kiếm foo.bar? Tìm foo trong bảng băm biến cục bộ, sau đó tìm bar trong bảng băm của foo. Trong một số ngôn ngữ động, như Python và Ruby, có thể có các cuộc gọi tra cứu/phương thức bổ sung để triển khai các thuộc tính được tạo động.

Tất cả các tra cứu này là rất khó để thực hiện nhanh chóng. Python có một trong những triển khai bảng băm được điều chỉnh tốt nhất trên thế giới, và JavaScript đã có hàng triệu đô la tiền nghiên cứu đổ vào làm cho nó nhanh chóng. Những chiến thuật này hoạt động - so sánh JavaScript của Chrome với IE 5 để xem chỉ bao nhiêu - nhưng chúng nhiều, khó khăn hơn nhiều so với việc chỉ tạo các cuộc gọi hàm tĩnh.


Tôi nên đề cập đến cách ngôn ngữ "động" có thể thay đổi. Python có nhiều cách khác nhau để tương tác với các tra cứu biến, điều này rất tốt trong một số trường hợp, nhưng làm cho việc tối ưu hóa rất khó. Các ngôn ngữ động khác, chẳng hạn như Common Lisp và Smalltalk, có thể cạnh tranh đồng đều với các ngôn ngữ tĩnh trong nhiều trường hợp sử dụng vì tra cứu động/sửa đổi được kiểm soát nhiều hơn.

+0

Có thể chỉ định các kiểu tĩnh trong Common Lisp, khi bạn cảm thấy cần thiết. Việc triển khai xây dựng cho tốc độ có thể tạo ra mã rất nhanh. –

0

Đó là vì ngôn ngữ được nhập tĩnh thường được biên dịch thành mã máy trong khi ngôn ngữ được nhập động được trong hầu hết các trường hợp do một thông dịch viên điều hành.

+1

Dường như quá đơn giản hóa một chút. Không phải tất cả các ngôn ngữ được nhập tĩnh đều được biên dịch thành mã máy, bao gồm bất kỳ ngôn ngữ CLR hoặc ngôn ngữ JVM tĩnh nào. Không phải tất cả các ngôn ngữ được gõ động được diễn giải, ví dụ nhiều Lisps có thể được biên dịch xuống bytecode, và có nhiều trình biên dịch cho Python và PHP. – Juliet

+0

Lisp thường có thể được biên dịch thành mã máy. –

+0

Hầu hết các triển khai tốt của Lisp thường được biên dịch thành mã máy. Một số không có thông dịch viên, họ chỉ làm biên dịch JIT. –

10

Một số loại tối ưu hóa thời gian biên dịch chỉ có thể được thực hiện nếu loại chính xác của biến được biết.

Ngôn ngữ được nhập động cũng thường có thêm logic để xác định loại và để đảm bảo rằng giá trị là chính xác cho loại.

10

Nhìn vào ví dụ python này:

def fact(n): 
    if n==0: 
     return n 
    return n*fact(n-1) 

n là gì? Nó là một con số? Nó là một String? Đây có phải là lớp bạn đã xác định trước đó không? Không có cách nào cho trình biên dịch biết đầu vào sẽ nhận được gì. Bạn phải làm rất nhiều kiểm tra tại thời gian chạy, có nghĩa là bạn đang làm nhiều công việc tiềm ẩn cho các hoạt động đơn giản.

+2

Trên thực tế một số languagse, như Ocaml, F # và Haskell hỗ trợ kiểu suy luận (http://en.wikipedia.org/wiki/Type_inference), do đó trình biên dịch có thể xác định kiểu dữ liệu của biến dựa trên cách sử dụng của nó mà không có chú thích kiểu . Ví dụ, 'n == 0', một phép kiểm tra bình đẳng cho một số nguyên nghĩa là 'n' là một số nguyên. Vì trình biên dịch biết 'n' là một số nguyên, nên 'return n' hàm ý hàm trả về một số nguyên. Vì vậy, chúng ta có thể xác định rằng hàm lấy một int và trả về một int. – Juliet

+2

@ Công chúa: Ah, nhưng đó là một máy tính có kích thước int hoặc một bignum? Bạn vẫn phải kiểm tra điều này (nhưng nó có thể được thực hiện hiệu quả) – simon

+0

Bạn vẫn nghĩ quá tĩnh - cách biên dịch lại động và đặc tả (đọc các bài báo tự). Trên thực tế, bằng cách có thông tin kiểu thực tế xung quanh, một trình biên dịch động thậm chí có thể tạo mã nhanh hơn trình biên dịch tĩnh, vì nó thậm chí có thể biết về các dãy giá trị vv. nhanh chóng ... – blabla999

4

Ngôn ngữ được nhập động phải làm cho tất cả các kiểm tra của họ trong thời gian chạy vì loại có thể thay đổi trong quá trình thực thi.

Ngôn ngữ được nhập tĩnh giải quyết tất cả các loại trong thời gian biên dịch để chi phí được tiêu thụ trước, một lần.

Đây là lý do chính khiến ngôn ngữ nhập động thường chậm hơn. Nhưng có những thứ khác để suy nghĩ. Rất nhiều phụ thuộc vào trình biên dịch hoặc thông dịch viên, việc thực hiện GC, bố trí bảng công văn và các thuật toán tra cứu cùng với các tối ưu hóa khác.

Tất cả phụ thuộc vào việc triển khai: Ngôn ngữ được nhập động có thể nhanh hơn ngôn ngữ được biên dịch, nó chỉ mất nhiều công sức hơn để thực hiện việc này.

+0

Có thể biên dịch các ngôn ngữ động ;-) – Ponkadoodle

+0

Bạn có nghĩa là thực thi rất tốt ngôn ngữ được nhập động có thể nhanh hơn việc thực thi rất kém ngôn ngữ được gõ tĩnh. Ví dụ: – niagr

1

Câu hỏi của bạn hơi lệch vì ngôn ngữ được nhập động thực sự không chậm. Nhiều ví dụ có thể là trong thực tế, nhưng các ví dụ khác là nhanh (nơi nhanh có nghĩa là "có thể so sánh hợp lý với c" hoặc một cái gì đó tương tự, cf lisp chung).

Nhiều ngôn ngữ động đang chạy trên máy ảo hoặc thậm chí được diễn giải, điều này có thể gây ra sự chậm trễ có thể tránh được. Ở một mức độ nhất định, có các tối ưu hóa có sẵn cho các trình biên dịch ngôn ngữ tĩnh (hoặc các trình động mà đã thực hiện đúng các lời hứa không phải là năng động về điều gì đó) mà không thể có trong một tình huống hoàn toàn năng động.

Tuy nhiên, nếu bạn đang suy nghĩ về sự khác biệt giữa say, python và C++ chẳng hạn, nó không phải là động so với tĩnh thực sự là vấn đề.

+0

Cũng có thể lưu ý rằng một số trình dịch Javascript bytecode gần đây thường hoạt động nhanh như C++. – eyelidlessness

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