2012-10-14 13 views
12

Tôi có một vấn đề lớn. Tôi có một thư viện chung, được sử dụng trên toàn bộ dự án của tôi. Thư viện này sử dụng mạnh mẽ boost.spiritboost.fusion. Thật không may, thư viện là khoảng. Kích thước 700Mb. Tất cả mã sử dụng boost.spirit được sử dụng và hoạt động tốt. Những bước nào có thể được thực hiện để giảm kích thước đầu ra của nó? Có một công cụ có thể giúp để xác định những gì instantiations mẫu hầu hết các không gian?Làm thế nào để giảm kích cỡ đầu ra của mã C++ mẫu nặng?

Lúc đầu, tôi quyết định di chuyển tất cả mã nhận biết tinh thần sang tệp cpp. Thứ hai, tôi sẽ thử các cờ biên dịch khác nhau để tối ưu hóa cho kích thước. Tôi không biết phải làm gì khác.

Cập nhật (xem chi tiết)

Tôi đang sử dụng GNU toolchain. Thư viện lớn thực sự là một thư viện tĩnh. Thực thi, sử dụng thư viện 700Mb này có kích thước 200Mb. Ít nhất một nửa mã nằm trong tệp * .h. Một số boost.spirit ngữ pháp (mẫu rất nặng) cũng nằm trong tệp * .h.

Chúc mừng!

Trả lời

5

Moving mã nhận biết tinh thần cho các tệp .cpp là bước đầu tiên tốt, nó có thể chưa hoàn chỉnh mặc dù bạn đề cập đến ngữ pháp tinh thần trong các tệp tiêu đề.

  1. Đảm bảo rằng không xuất xứ ngữ pháp/quy tắc nào bên ngoài thư viện. Nếu bạn có các thư mục điển hình là include/src, hãy di chuyển các tệp đó (ngay cả khi tiêu đề) trong thư mục src.

  2. Đánh dấu tất cả các biểu tượng đó là nội bộ vào thư viện. Họ không thể truy cập từ bên ngoài thư viện cả.Có các pragmas/thuộc tính cụ thể tùy thuộc vào trình biên dịch của bạn, trên gcc tra cứu visibility attribute: __attribute__ ((visibility ("internal"))). Điều này giúp trình biên dịch tối ưu hóa chúng cho phù hợp, đáng chú ý là một trình biên dịch có thể phát ra mã của một hàm ngay cả khi nó inline nó tại một trang web gọi, chỉ trong trường hợp địa chỉ hàm này được thực hiện. Tuy nhiên, với khả năng hiển thị nội bộ, vì nó biết mã sẽ không rời khỏi đối tượng, nó có thể bỏ qua chức năng này.

  3. tôi dường như nhớ một lá cờ để cầu chì các cơ quan chức năng giống hệt nhau nhưng dường như không thể tìm thấy một lần nữa ...

+0

Cảm ơn thuộc tính 'visibility', không biết về nó. – Lazin

2

Một vài gợi ý:

  • nếu có thể, hãy cố gắng tái sử dụng các mẫu instantiations cùng (như là một đơn giản, và giả tạo, ví dụ, một std::vector<int>std::vector<float> sẽ có cấu trúc bên trong cùng và có thể cả hai chỉ điều trị dữ liệu phần tử của chúng dưới dạng các đốm màu 4 byte mờ đục, vì vậy người ta có thể ủy quyền cho người khác và chỉ hoạt động như một trình bao bọc mà chỉ quay trở lại đúng loại, sao cho nội bộ của véc-tơ chỉ được khởi tạo cho một loại, thay vì hai.

  • hãy thử trình biên dịch khác. Một số trình biên dịch sử dụng lại các mẫu instantiations giống hệt nhau mà nó sẽ không ảnh hưởng đến ngữ nghĩa chương trình, trong khi các trình biên dịch khác bảo thủ hơn.

  • theo dõi sát những gì được xuất từ ​​thư viện. Các biểu tượng không được xuất và không được tham chiếu bên trong, có thể bị xóa bởi trình liên kết. (Tất nhiên, nếu bạn đang xây dựng một thư viện tĩnh, điều này sẽ không khởi động cho đến khi nó được liên kết với một tệp thực thi. Để giảm kích thước của thư viện, bạn có thể thử làm cho nó trở thành thư viện động)

Nhưng cuối cùng, có vẻ như bạn chỉ phải sử dụng thư viện ít mẫu hơn. (Hoặc viết một phân tích cú pháp đơn giản hơn bạn đang có)

+1

Một trong những vấn đề với việc sử dụng lại mẫu instantiations là bình thường mỗi chức năng phải có một địa chỉ khác và ngăn cản việc hợp nhất các chức năng khác nhau với nhau ngay cả khi mã thực thi của chúng khác nhau. Tôi không nghĩ rằng VC++ quan tâm nhiều cho điều đó, tuy nhiên stricto sensu tối ưu hóa này chỉ có sẵn nếu trình biên dịch có thể chứng minh rằng các địa chỉ không được sử dụng trong chương trình ... –

+0

@MatthieuM. đúng, đó là lý do tại sao không phải tất cả trình biên dịch đều làm điều đó. Nó thường là một tối ưu hóa khá an toàn (bạn không thường so sánh các địa chỉ hàm, và khi bạn làm, và tôi nghi ngờ trong hầu hết các trường hợp nó không hợp lệ, nó khá đơn giản để trình biên dịch phát hiện nó) - tuy nhiên, nó làm thắc mắc về kích thước thực thi của mã mẫu nặng – jalf

4

--ffunction-sections sẽ đưa từng chức năng trong phân khúc riêng của mình. Không hữu ích theo cách riêng của nó, nhưng trình liên kết có thể xóa các phần không sử dụng với --gc-sections. Bây giờ không có --function-segments, điều này sẽ chỉ hoạt động nếu toàn bộ tệp nguồn không được sử dụng, tức là với mức độ chi tiết điên rồ.

Rõ ràng bạn cần thuộc tính hiển thị được Matthieu đề cập, tất cả các chức năng khác trong thư viện đều "được sử dụng" nhờ có khả năng hiển thị.