Đi nhanh như thế nào?


39

Go là một trong số ít các ngôn ngữ được cho là chạy 'gần với kim loại', tức là nó được biên dịch, gõ tĩnh và thực thi mã nguyên bản, không có VM. Điều này sẽ mang lại cho nó một lợi thế về tốc độ so với Java, C # và tương tự. Tuy nhiên, có vẻ như nó đứng sau Java (xem phần Bắn ngôn ngữ lập trình )

Tôi cho rằng các trình biên dịch kém trưởng thành chịu trách nhiệm rất lớn cho việc này, nhưng còn lý do nào khác không? Có bất cứ điều gì vốn có trong thiết kế của Go sẽ ngăn nó chạy nhanh hơn, giả sử, Java? Tôi có một cái nhìn rất không phức tạp về các mô hình thời gian chạy, nhưng có vẻ như về nguyên tắc, nó sẽ có thể chạy nhanh hơn Java, nhờ thực thi mã gốc.


3
Với một trình biên dịch thông minh (và / hoặc VM và / hoặc trình biên dịch JIT), một ngôn ngữ nhất định luôn có thể đi nhanh hơn (tốt, có những hạn chế về mặt vật lý, nhưng đó là nó). Tất nhiên, sự thật này không giúp được ai, miễn là trình biên dịch thông minh hiệu quả này không có ở đó. Lưu ý rằng Java đã có những triển khai thông minh một cách hiệu quả và chúng cực kỳ thông minh. Một thực tế khác của cuộc sống là việc chạy mã có ít nhất ảnh hưởng đến hiệu năng thời gian chạy như khi thực hiện.

1
Tôi hiểu điều đó, nhưng tôi đã tự hỏi liệu có hợp lý không khi mong đợi tốc độ của Go khớp / vượt qua, ví dụ Java khi trình biên dịch của nó đáo hạn.
Greg Slodkowicz

17
Ngôn ngữ lập trình không có tốc độ. Không thực hiện ngôn ngữ. Một triển khai ngôn ngữ nhất định có tốc độ cho một số đầu vào nhất định và tốc độ này có thể rất lớn tùy thuộc vào đầu vào.

8
Hãy đánh thức tôi dậy .. trước khi bạn đi ... WHAM! . Xin lỗi, tôi không thể cưỡng lại. Đây là những lá cờ .. đây những lá cờ ..
Tim Post

2
@delnan - Hoặc nói "Java" dễ dàng hơn nhiều so với nói "Java (TM) SE Runtime Môi trường (bản dựng 1.6.0_25-b06) Máy chủ 64-bit Java HotSpot (TM) (xây dựng 20.0-b11 , chế độ hỗn hợp) ":-)
igouy

Câu trả lời:


46

Về mặt thiết kế ngôn ngữ, thực sự không có bất cứ điều gì khiến Go đi chậm hơn Java nói chung. Trong thực tế, nó cho phép bạn kiểm soát nhiều hơn về bố cục bộ nhớ của các cấu trúc dữ liệu của bạn, vì vậy đối với nhiều tác vụ phổ biến, nó sẽ nhanh hơn một chút. Tuy nhiên, trình biên dịch Go chính, trình lập lịch biểu, trình thu gom rác, thư viện regrec và nhiều thứ khác không được tối ưu hóa đặc biệt. Điều này đang dần được cải thiện, nhưng trọng tâm dường như là hữu ích, đơn giản và đủ nhanh để giành chiến thắng trong các điểm chuẩn vi mô.

Trong điểm chuẩn được liên kết, Go thua lớn với Java trên cây nhị phân và kiểm tra regrec. Đó là những bài kiểm tra của hệ thống quản lý bộ nhớ và thư viện regrec tương ứng. Quản lý bộ nhớ của Go có thể nhanh hơn và chắc chắn sẽ cải thiện theo thời gian và thư viện regrec tiêu chuẩn hiện tại là một trình giữ chỗ để triển khai tốt hơn nhiều sắp tới. Vì vậy, mất hai thứ đó không đáng ngạc nhiên, và trong tương lai gần, biên độ sẽ hẹp hơn.

Đối với điểm chuẩn k-nucleotide, hơi khó so sánh vì mã Java dường như đang sử dụng một thuật toán khác. Mã Go chắc chắn sẽ được hưởng lợi từ các cải tiến trình biên dịch, trình lập lịch biểu và phân bổ sắp tới, ngay cả khi được viết, nhưng ai đó sẽ phải viết lại mã Go để làm điều gì đó thông minh hơn nếu chúng ta muốn so sánh chính xác hơn.

Java giành chiến thắng trong tiêu chuẩn mandelbrot bởi vì tất cả đều là số học và vòng lặp dấu phẩy động và đây là nơi tuyệt vời để JVM tạo mã máy thực sự tốt và nâng mọi thứ trong thời gian chạy. Go, so sánh, có một trình biên dịch khá đơn giản mà không cần nâng, bỏ kiểm soát hoặc tạo mã máy thực sự chặt chẽ hiện tại, vì vậy không có gì đáng ngạc nhiên khi nó bị mất. Tuy nhiên, ta nên nhớ rằng thời gian Java không tính thời gian khởi động JVM hoặc số lần cần chạy để JVM chạy JIT một cách độc đáo. Đối với các chương trình dài hạn, điều này không liên quan, nhưng nó quan trọng trong một số trường hợp.

Đối với phần còn lại của các điểm chuẩn, Java và Go về cơ bản là cổ, với Go chiếm ít bộ nhớ hơn và trong hầu hết các trường hợp ít mã hơn. Vì vậy, trong khi Go chậm hơn Java trong một số thử nghiệm đó, thì Java khá nhanh, Go so sánh khá tốt và Go có thể sẽ nhanh hơn đáng kể trong tương lai gần.

Tôi đang mong chờ khi gccgo (trình biên dịch Go sử dụng codegen gcc) đã hoàn thiện; điều đó sẽ khiến Go trở nên phù hợp với C cho nhiều loại mã, điều này sẽ rất thú vị.


2
Làm tốt lắm, để hiểu rằng luôn cần phải xem mã nguồn và kiểm tra xem cái gì đã được thực hiện!
igouy

1
Trên Java thời gian khởi động cho các chương trình, xem shootout.alioth.debian.org/help.php#java
igouy

2
Đó là chính xác những loại câu trả lời tôi đã hy vọng cho, cảm ơn!
Greg Slodkowicz

Sử dụng ít mã & bộ nhớ hơn, biên dịch thành mã máy, được thiết kế tốt hơn. Tất cả điều này chiếm trên bất lợi tốc độ.
Moshe Revah

22
  1. Thậm chí không cần nói vấn đề nào đã được giải quyết, toàn bộ điểm chuẩn là vô nghĩa.
  2. Cả JVM và CLR đều sử dụng JIT để tạo mã máy. Không có lý do gì nên chậm hơn. Nó chỉ tốn chi phí cho lứa tuổi của bạn để khởi động.
  3. Go được thiết kế để xây dựng nhanh . Bạn không có hàng tấn thời gian biên dịch và tối ưu hóa thời gian khởi động. Đi biên dịch thư viện tiêu chuẩn của riêng nó vào thời điểm ứng dụng Java đã khởi động.

Có thể đi nhanh hơn trong thời gian chạy? Vâng. Sẽ đi nhanh hơn bao giờ hết? Tôi không biết. Có thể các trình xây dựng trình biên dịch sẽ thêm tối ưu hóa tùy chọn với chi phí thời gian biên dịch. Nhưng tôi không nghĩ rằng họ có nhiều hứng thú với điều đó. Họ làm việc tại Google.
Những gì họ muốn là một ngôn ngữ cho phép phát triển nhanh và thực hiện tốt những gì họ làm. Chết tiệt, ngay cả khi điểm chuẩn đó là đáng tin cậy, điều đó có nghĩa là chúng nhanh bằng một nửa so với C và nhanh gấp 14 lần Python. Điều này là quá đủ tốt.
Phần cứng là rẻ, mã là đắt tiền. Mã có xu hướng trở nên lớn hơn và chậm hơn khi bạn đầu tư tiền, phần cứng trở nên rẻ hơn và nhỏ hơn. Bạn muốn có một ngôn ngữ, không yêu cầu 4 khung và 2000 lớp để hoàn thành bất kỳ điều gì hữu ích.
Không có gì vốn có trong thiết kế của Go, điều đó làm cho nó chậm. Tuy nhiên, có một cái gì đó vốn có trong các nhà thiết kế của Go, khiến nó chậm hơn lắp ráp: lẽ thường.


1
Hầu hết (tất cả?) JITs biên dịch trong thời gian chạy, không phải khi mã được tải lần đầu tiên. Mã máy này có thể hoàn toàn không được tạo cho một số mã và cũng có thể dễ dàng bị vô hiệu hóa, ví dụ: nếu objstrong đó for (obj : objs) { obj.meth() }có các triển khai khác nhau methmỗi lần và JIT cố gắng nội tuyến nó. Tất nhiên, tất cả điều này thực sự là một lợi ích trong các trường hợp phổ biến, nhưng vẫn đáng chú ý.

@delnan: V8 JIT bất kỳ mã nào trước khi thực hiện nó. Ngoài ra, LLVM được xây dựng với ý tưởng JITting, do đó (với một số nỗ lực tất nhiên), bạn có thể thực hiện bất kỳ tối ưu hóa nào chỉ trong thời gian, điều đó sẽ xảy ra vào thời gian biên dịch. Tuy nhiên, một số tối ưu hóa nhất định, chẳng hạn như phân tích thoát chỉ thực sự hoạt động với JIT.
back2dos

3
>> Thậm chí không cần nói vấn đề nào đã được giải quyết << Hãy nhìn và bạn sẽ thấy rằng các trang web đó nói rằng vấn đề nào đã được giải quyết. Trên thực tế, bạn sẽ tìm thấy mã nguồn chương trình, xây dựng lệnh, chạy lệnh, phiên bản triển khai ngôn ngữ, ya da ya da ya
igouy

10

Tôi cũng nhận thấy rằng Go đặc biệt chậm trong điểm chuẩn regex-dna . Russ Cox đã giải thích lý do tại sao Go không phải là người biểu diễn trong tiêu chuẩn cụ thể này . Lý do là gói regrec của Go đang sử dụng một thuật toán kết hợp khác hoạt động kém trong điểm chuẩn cụ thể này nhưng có thể nhanh hơn nhiều so với các điểm chuẩn khác. Ngoài ra, Ruby, Python và các ngôn ngữ kịch bản lệnh khác đang sử dụng triển khai C của thuật toán so khớp regrec khác .

Cuối cùng, Trò chơi Điểm chuẩn Ngôn ngữ Máy tính bao gồm các điểm chuẩn vi mô có thể không phản ánh chính xác nhiều đặc điểm của các ngôn ngữ được đo và thậm chí là trung gian cho các hiển thị sai. Bài viết nghiên cứu này, được xuất bản gần đây bởi Google cung cấp một cái nhìn tổng quan chính xác hơn về một số đặc điểm ngôn ngữ của Go, Scala, Java và C ++ - đặc biệt là phần "Phân tích hiệu suất V.". Vì vậy, cuối cùng, Go gần như đói bộ nhớ như Java (81% bộ nhớ của Java) và tiêu thụ bộ nhớ thậm chí 170% so với Scala (không thể tìm thấy trong bài báo xem mức tiêu thụ bộ nhớ của JVM).

Nhưng một lần nữa, Go vẫn còn trẻ và vẫn đang được phát triển mạnh mẽ (thay đổi API)! Nhiều cải tiến đang đến sớm.


3
>> Tài liệu nghiên cứu này, được xuất bản gần đây bởi Google << Nó không phải là một bài nghiên cứu và nó không được xuất bản bởi Google. Đó là một báo cáo kinh nghiệm của một nhân viên Google được trình bày tại hội thảo Scala "Scala Days 2011".
igouy

>> có thể không phản ánh chính xác nhiều đặc điểm của các ngôn ngữ được đo và thậm chí là trung gian cho các hiển thị sai << Điều đó đúng với các chương trình "nhận dạng vòng lặp" và có thể đúng với mọi so sánh hiệu suất giữa các ngôn ngữ lập trình khác nhau. Trên thực tế, tác giả nói với bạn - "Chúng tôi không khám phá bất kỳ khía cạnh nào của cơ chế đa luồng hoặc cơ chế cấp cao hơn ... chúng tôi cũng không thực hiện tính toán số nặng ..."
igouy

@igouy Trên trang bìa, bạn có thể đọc "Google" và mọi thứ liên quan đều được đề cập với các tài liệu tham khảo tương ứng. Vậy tại sao nó không phải là "bài nghiên cứu, được xuất bản bởi Google" nếu Google được đề cập với địa chỉ trụ sở chính? Tài liệu nghiên cứu không phải là một lĩnh vực chỉ dành cho học viện.
Alex

Trên trang bìa, bạn có thể đọc địa chỉ gửi thư mà tác giả có thể được liên lạc và địa chỉ email của tác giả. Kiểm tra URL của pdf mà bạn đã đăng. Lưu ý tên miền - days2011.scala-lang.org - Hội thảo Scala Days 2011 "
igouy

1

Go nhanh hơn Python và chậm hơn Java một chút. Trải nghiệm sơ bộ của tôi đã tìm thấy Go to hơn (1-2 bậc độ lớn) nhanh hơn Python và chậm hơn khoảng 10-20% so với Java. Tuy nhiên, Go nhanh hơn Java một chút nếu được sử dụng với lõi tứ (x64). Go cũng hiệu quả hơn rất nhiều về bộ nhớ RAM.

Tôi muốn thêm một số điểm về tiềm năng của Go về hiệu năng so với Java và Python. Go cho phép nhiều hơn những thứ mà C làm liên tục cho phép C vượt trội hơn hầu hết các ngôn ngữ khác. Lỗi bộ nhớ cache là khá quan trọng để tránh mã hiệu suất cao. Giảm nhớ cache yêu cầu kiểm soát bố cục bộ nhớ của cấu trúc dữ liệu của bạn. Go cho phép bạn làm điều đó. Java không làm cho việc tránh vỡ bộ nhớ và bộ nhớ cache trở nên khó khăn hơn.

Ngay bây giờ Java thường chạy nhanh hơn Go, bởi vì trình thu gom rác Java phức tạp hơn rất nhiều. Mặc dù không có lý do gì bộ thu gom rác Go không thể tốt hơn nhiều. Việc tạo mã cũng có khả năng tốt hơn rất nhiều cho Java tại thời điểm này. Go có rất nhiều tiềm năng để cải thiện, ví dụ như có hỗ trợ cho các hướng dẫn vectơ, v.v.

Vì vậy, tôi nghĩ rằng nó thực sự chỉ là một câu hỏi về thời gian trước khi vượt qua Java. Mặc dù giống như với bất kỳ mã ngôn ngữ nào có thể sẽ không tự động nhanh hơn bằng cách được viết bằng Go. Bạn phải sử dụng các phương tiện mà ngôn ngữ cung cấp cho bạn. Tôi muốn nói Go chỉ đơn giản là cung cấp thêm cơ hội để điều chỉnh mã của bạn.

Dù sao, đó chỉ là một kinh nghiệm của nhà phát triển.


4
Đây là một câu hỏi 8 năm tuổi và sức mạnh tính toán giá rẻ đã khiến nó trở nên không liên quan. Câu trả lời của bạn cũng dựa trên "cảm giác của bạn" chứ không phải dữ liệu cứng. Tôi không có ý làm bạn nản lòng, nhưng ...
Kayaman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.