2011-12-26 36 views
10

D là một trong những ngôn ngữ lập trình nhanh nhất để biên dịch, nếu không phải là nhanh nhất, nhưng điều này không phải luôn luôn như vậy. Mọi thứ trở nên rất chậm khi unittest được bật. Dự án hiện tại của tôi có 6-7 mô-đun (~ 2000 LOC), với mỗi một trong số chúng có unittests cũng chứa điểm chuẩn. Dưới đây là một vài con số từ dự án hiện tại của tôi:Tại sao quá trình biên soạn D mất quá lâu?

dmd -O -noboundscheck mất 0m1.287s

dmd -O -release -noboundscheck mất 0m1.382s

dmd -O -inline -noboundscheck mất 0m1.499s

dmd -O -inline -release -noboundscheck mất 0m3.477s

thêm -unittest cho bất kỳ một trong những ý trên tăng đáng kể compi Hiện lation:

dmd -O -inline -release -noboundscheck -unittest mất 0m21.918s

và đôi khi nó bị treo DMD:

time dmd -O t1.d -inline -noboundscheck -version=Double -unittest mất 0m2.297s Internal error: ../ztc/gdag.c 776

Evidentially, unittest là buggy nhưng đồng thời nó đã trở thành một phần quan trọng của dự án của tôi. Tôi muốn biết nếu sự chậm lại là bình thường hay nó là một cái gì đó đang được làm việc trên? Dự án của tôi đang phát triển và với mọi bản dịch mới nhất không được biên soạn sẽ mất nhiều thời gian hơn và lâu hơn. Giải pháp duy nhất tôi biết là tắt -release-inline, nhưng điều đó không phải lúc nào cũng mong muốn.

+0

Bạn có nhiều bản mẫu tức thì trong các bài kiểm tra đơn vị của mình không? –

+0

@CyberShadow Vâng, nó chủ yếu là mẫu instantiations vì có rất nhiều chương trình chung chung. – Arlen

+0

Đó là lý do rất có thể. Hãy thử di chuyển các phần không chung chung của mã của bạn bên ngoài các mẫu. –

Trả lời

1

Một cải tiến hiệu suất rất nhỏ có thể di chuyển mẫu instantiation đến module-phạm vi, thông qua một version(unittest) block, ví dụ:

auto foo(T)(T t) { return t; } 

version(unittest) { 
    alias foo!int fooInt; 
} 

unittest { 
    auto x = fooInt(1); 
} 

Profiling này, tôi nhận được xung quanh ~30msec cải thiện tốc độ nếu tôi sử dụng mẫu ví dụ aliased trong 5000 khối không liên kết tương đương qua auto x = fooInt(1), so với việc trực tiếp hóa nó trực tiếp trong mỗi khối không nhất quán qua auto x = foo(1) (điều này thực sự mở rộng thành auto x = foo!int(1)).

Điều này rất có thể sẽ chỉ hoạt động đối với trường hợp bạn có rất nhiều lần hủy tạo ra cùng một mẫu mẫu.

+0

mẫu hoặc mã chung không có vẻ là vấn đề. Nó làm giảm thời gian biên dịch, nhưng nhìn chung nó không phải là vấn đề. Tôi refactored mã của tôi và chỉ nhận thấy 4-6 giây khác biệt. Nó vẫn còn rất chậm xem xét thực tế là nó chỉ có 2k dòng mã. Nó có một cái gì đó để làm với tối ưu hóa. – Arlen

+0

Cá nhân tôi không sử dụng '-release' khi unittesting. '-release- loại bỏ bất kỳ sự khẳng định nào mà tôi có thể có mà có thể làm cho các unittests của tôi vượt qua khi họ không nên. –

+1

@AndrejM. Miễn là bạn biên dịch với '-unittest', các xác nhận sẽ không bị xóa, ngay cả khi bạn biên dịch bằng' -release'. –

4

DMD có vấn đề đã biết với các tối ưu hóa: long blocks of code optimise with an O(n^2) algorithm, do đó, các chức năng dài mất nhiều thời gian để biên dịch với các tối ưu hóa.

Hãy thử tách mã của bạn thành các hàm nhỏ hơn và bạn sẽ có thời gian biên dịch tốt hơn trong thời gian chờ đợi. Bạn có thể làm được điều này khá dễ dàng bằng cách sử dụng chức năng inline:

void foo() 
{ 
    // lots of code 
    // more code 
} 

Rẽ này vào:

void foo() 
{ 
    void block1() 
    { 
     // lots of code 
    } 
    block1(); 

    void block2() 
    { 
     // more code 
    } 
    block2(); 
} 

này đã làm việc cho tôi.

+0

Tôi nghĩ rằng bạn có nghĩa là chức năng lồng nhau? –

0

Tôi đã thay thế nhiều mã chung, nhưng nó chỉ giảm thời gian biên dịch xuống còn 4-5 giây.Mọi thứ trở nên tồi tệ hơn, và tôi tin rằng trình biên dịch có lẽ là vấn đề:

time dmd -O -inline -release -noboundscheck -unittest mất 0m30.388s

time dmd -O -inline -release -noboundscheck mất 0m11.597s

time dmd -inline -release -noboundscheck -unittest mất 0m1.884s

Khi -O, -inline, -release, và -unittest là tất cả các thiết lập, biên dịch mất nhiều thời gian nhất. Giảm -O làm giảm đáng kể thời gian biên dịch. Do đó, để giảm thời gian biên dịch khi hủy kết nối, hãy thả (các) cờ tối ưu hóa. Đối với các bộ sưu tập thông thường, bạn có thể sử dụng một trong ba (-inline, -release, -unittest) mà không có vấn đề gì. Theo kinh nghiệm của tôi, đó là sự kết hợp của cả ba nguyên nhân khiến quá trình biên dịch mất nhiều thời gian nhất thứ hai, và dài nhất khi -unittest được thiết lập là tốt.

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