2011-12-13 33 views
11

Sự khôn ngoan được chấp nhận là việc sử dụng cấu trúc như Dim dict As New Dictionary kém hiệu suất hơn Dim dict As Dictionary/Set dict = New Dictionary.Hiệu năng kém của Excel VBA có tự động hóa một huyền thoại không?

Giải thích là ví dụ trước - tự động-instantiation - defers instantiation cho đến khi sử dụng đầu tiên của biến dict. Và do đó, mỗi lần dict được tham chiếu, mã được biên dịch trước tiên phải kiểm tra xem dict có bằng Không.

Nhưng nó xảy ra với tôi rằng mã được biên dịch thực hiện điều này. Bạn sẽ gặp lỗi bất kỳ lúc nào bạn cố gắng sử dụng tham chiếu đối tượng là Nothing.

Vì vậy, để tôn vinh khoa học, tôi đã thực hiện một số thử nghiệm. Và kết quả cho thấy không có sự khác biệt về hiệu suất giữa hai phương pháp. (Chạy trên Excel 2007)

Gọi "tạo từ điển & thêm 2 mục" 100.000 lần.

  • Explicit: 16,891ms/Auto: 16,797ms (Auto 94ms nhanh hơn)
  • Explicit: 16,797ms/Auto: 16,781ms (Auto 16ms nhanh hơn)

Đảo ngược thứ tự của các cuộc gọi thử nghiệm :

  • Auto: 16,766ms/Explicit: 16,812ms (Auto 46ms nhanh hơn)
  • Auto: 16,828ms/Explicit: 16,813ms (15ms Explicit nhanh hơn)

Gọi "tạo từ điển & thêm 6 mục" 100.000 lần.

  • Auto: 17,437ms/Explicit: 17,407ms (30ms Explicit nhanh hơn)
  • Auto: 17,343ms/Explicit: 17,360ms (Auto 17ms nhanh hơn)

Tạo từ điển và thêm 100.000 mặt hàng.

  • Auto: 391ms/Explicit: 391ms (Tương tự)

Tạo từ điển và thêm 1.000.000 mục.

  • Auto: 57,609ms/Explicit: 58,172ms (563ms Auto nhanh hơn)
  • Explicit: 57,343ms/Auto: 57,422ms (79ms Explicit nhanh hơn)

tôi thấy không có gì để cho biết rằng tự động khởi tạo là một mối quan hệ hoạt động kém với sự khởi tạo rõ ràng. (Để được rõ ràng, vì những lý do khác, tôi sẽ tránh tự động instantiation nhưng tôi chỉ quan tâm đến góc hiệu suất ở đây.)

Vì vậy, đây là một huyền thoại?

CẬP NHẬT

Hãy để tôi đặt ra tại sao các lập luận hiệu suất không có ý nghĩa đối với tôi. Người ta nói rằng

x.Add("Key", "Item") 

trong một đối tượng tự động khởi tạo tương đương như sau:

If x is Nothing then 
    Set x = New Dictionary 
End If 
x.Add("Key", "Item") 

mà làm cho nó trông giống như "overhead đáng sợ" nếu bạn đang gọi điện thoại hàng ngàn này lần. Nhưng trong trường hợp instantiation rõ ràng, đó là chính xác những hình thức của logic được tạo ra trong phiên bản biên dịch của mã này:

If x is Nothing Then 
    Err.Raise "Object variable not set..." 
End If 
x.Add("Key", "Item") 

Nó không nhất thiết phải làm theo tự động có nghĩa là lâu hơn, đó là lý do tại sao tôi đang hỏi liệu có bất kỳ sự thật nào về điều này. Tôi tự hỏi liệu tôi đã xác định được một trong số những huyền thoại về hiệu suất chưa được kiểm chứng chưa.

+0

Nó thực sự chỉ là ngữ nghĩa "Không có gì" khác nhau đặt 'As New' hơi khác với' Dim/Set'. Như bạn nói cái gọi là chi phí liên quan đến một kiểm tra kiểu thời gian chạy là không thích hợp cho rằng trừ khi đối tượng được tự động kiểm tra thực sự * là * 'Nothing', không xảy ra nhiều hơn nếu nó là tham chiếu' Dim/Set'. –

+0

@Alex K, hướng dẫn về hiệu suất lâu đời này cho biết * mọi tham chiếu đến biến sẽ gọi kiểm tra "Nếu X là Không có gì" trong trường hợp tự động, biến Dim/Set sẽ không. Vì vậy, bạn phải kiểm tra nếu có một hit hiệu suất bất cứ khi nào bạn truy cập vào đối tượng sau khi khai báo, thay vì kiểm tra bản thân khai báo. –

+0

@JP Không đúng - Tôi đã google này sau câu hỏi SO khác mà tôi đã xem hôm nay. Ví dụ: http://www.cpearson.com/excel/classes.aspx Ví dụ khác: http://www.bettersolutions.com/vba/VUA113/LI912711911.htm –

Trả lời

5

Tôi biết có cách thánh thiện nếu không sao hoặc không mờ như mới, nhưng tôi chưa bao giờ nghe nói về nó được cho là tạo ra hiệu suất kém. Câu trả lời ngắn gọn là không thực sự. Có nó xả rác mã của bạn với kiểm tra unnessesary để xem nếu nó không phải là Không có gì, nhưng bạn sẽ không nhận thấy một sự khác biệt tốc độ nhờ vào các máy ngày nay. Nó giống như nói "cho looping hơn 10000 ký tự là nhanh hơn 10001. Để bắt đầu nhìn thấy bất kỳ sự khác biệt, bạn cần phải được looping thử nghiệm của bạn trong điều kiện cao hơn, như hàng triệu và hàng chục triệu. thuận nhưng không phải vì lý do hiệu suất.

  • bạn mất khả năng kiểm soát khi nó được khởi tạo
  • bạn mất khả năng kiểm tra nếu một đối tượng là không có gì
  • chênh lệch tốc độ hay không, nó xả rác mã của bạn với kiểm tra đơn nhất

Cấp nếu bạn chỉ sử dụng VBA để tự động hóa một số trang tính hoặc thao tác dữ liệu, có thể bạn sẽ không quan tâm, nhưng thời điểm bạn xem mã phức tạp hơn, mất khả năng kiểm tra nếu đối tượng là Không có gì và không kiểm soát khi nó được khởi tạo là rất lớn và có thể tạo ra những hành vi bất ngờ, chưa kể đến việc thử nghiệm một cơn đau ở mông. Tất cả điều đó để tiết kiệm một vài dòng mã.

Sau đó, có các trình tối ưu hóa vi mô sẽ cho rằng việc thêm bất kỳ thứ gì vào mã của bạn không cần thiết sẽ làm cho hiệu suất kém. Mặc dù họ đúng theo một số cách, bạn có thể tiết kiệm được 0.000000001 giây trong trường hợp này.

+0

Tôi đồng ý rằng bạn sẽ mất khả năng kiểm soát khi được khởi tạo; và tôi nghĩ rằng đó là một vấn đề nghiêm trọng hơn là thực tế không thể thiết lập đối tượng thành Không có gì. Nhưng câu hỏi đặt ra là "kiểm tra không cần thiết" - điều này có đúng không? Sau khi tất cả, nếu tôi viết Dim x là từ điển sau đó x.Add (1, "m") - Tôi sẽ nhận được một lỗi "biến đối tượng không được thiết lập" có nghĩa là biên dịch VBA đang kiểm tra nó anyway. –

+0

Kiểm tra trong khi biên dịch và kiểm tra trong thời gian chạy là rất khác nhau. Tôi tin tưởng, kiểm tra tại thời gian biên dịch là một điều tốt và để nó vào thời gian chạy là không. :) Và khi một lỗi là ném, nó không phải vì nó kiểm tra và nhận ra nó không thể làm điều đó, nó là nó TRIED để làm một cái gì đó mà nó không thể làm. – aevanko

+0

+1 "mất khả năng kiểm tra nếu một đối tượng là Không có gì và không kiểm soát khi nó được khởi tạo" - một lập trình viên phải được kiểm soát, không phải mã. Lợi ích hiệu suất từ ​​việc không có một "Không có gì" tiềm ẩn kiểm tra khi một biến được khai báo là lớn hơn nhiều so với việc xem xét này. – JimmyPena

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