Thay thế ld bằng vàng - có kinh nghiệm nào không?


81

Có ai đã cố gắng sử dụng goldthay thế ld?

gold hứa hẹn sẽ nhanh hơn nhiều ld, vì vậy nó có thể giúp tăng tốc các chu kỳ kiểm tra cho các ứng dụng C ++ lớn, nhưng liệu nó có thể được sử dụng làm drop-in thay thế cho ld không?

Có thể gcc/ g++trực tiếp gọi gold.?

Có bất kỳ lỗi hoặc vấn đề nào biết không?

Mặc dù goldlà một phần của GNU binutils từ một thời gian, tôi hầu như không tìm thấy "câu chuyện thành công" hoặc thậm chí "Howtos" nào trên Web.

( Cập nhật: thêm liên kết đến vàng và mục blog giải thích nó )

Câu trả lời:


53

Hiện tại, nó đang biên dịch các dự án lớn hơn trên Ubuntu 10.04. Tại đây bạn có thể cài đặt và tích hợp nó một cách dễ dàng với binutils-goldgói (nếu bạn gỡ bỏ gói đó, bạn sẽ nhận được gói cũ ld). Khi đó Gcc sẽ tự động sử dụng vàng.

Một số kinh nghiệm:

  • vàng không tìm kiếm trong /usr/local/lib
  • vàng không giả sử lib như pthread hoặc rt, phải thêm chúng bằng tay
  • nó nhanh hơn và cần ít bộ nhớ hơn (càng về sau càng quan trọng đối với các dự án C ++ lớn với nhiều bộ tăng cường, v.v.)

Điều gì không hoạt động: Nó không thể biên dịch nội dung hạt nhân và do đó không có mô-đun hạt nhân. Ubuntu thực hiện điều này tự động thông qua DKMS nếu nó cập nhật các trình điều khiển độc quyền như fglrx. Điều này không thành công với ld-gold(bạn phải loại bỏ vàng, khởi động lại DKMS, cài đặt lại ld-gold.


Cảm ơn, tôi nghĩ tôi sẽ thử - những hạn chế bạn đề cập dường như không có vấn đề gì trong trường hợp của tôi.
IanH

+1: cảm ơn vì đã chia sẻ kinh nghiệm. Còn về hiệu suất thì sao?
neuro

9
nó nhanh hơn đáng kể, đặc biệt là khi liên kết các thư viện tĩnh khổng lồ với nhau thành một tệp nhị phân nhưng chúng tôi không thực hiện bất kỳ phép đo nào khó khăn.
nob

2
@neuro Các phép đo của tôi là để liên kết nhiều đối tượng và tệp .a thành một tập hợp ~ 30 tệp .so (một tệp lớn, phần còn lại nhỏ) và 1 tệp thực thi cho một ứng dụng thương mại quan trọng. Chỉ đo thời gian liên kết và chạy thực hiện nối tiếp, tôi có tổng thời gian là 22,48 giây với ld so với 16,24 giây với vàng, cải thiện 6,24 giây cho mỗi bản dựng. Tuy nhiên, nếu tôi chạy make song song với 8 bộ vi xử lý, thì tổng sự khác biệt chỉ là 1,42 giây cho mỗi bản dựng. Việc sử dụng bộ nhớ tổng thể đã được cải thiện 42%, bất kể thực hiện song song. YMMV.
metal

@metal: cảm ơn rất nhiều vì các số liệu. Cải thiện việc sử dụng bộ nhớ trông rất tuyệt vời, ldthật là tham lam về nó.
neuro

40

Vì tôi đã mất một chút thời gian để tìm ra cách sử dụng vàng có chọn lọc (tức là không sử dụng liên kết biểu tượng trên toàn hệ thống), tôi sẽ đăng giải pháp ở đây. Nó dựa trên http://code.google.com/p/chromium/wiki/LinuxFasterBuilds#Linking_using_gold .

  1. Tạo một thư mục nơi bạn có thể đặt một kịch bản bằng keo vàng. Tôi đang sử dụng ~/bin/gold/.
  2. Đặt tập lệnh keo sau đây và đặt tên cho nó ~/bin/gold/ld:

    #!/bin/bash
    gold "$@"
    

    Rõ ràng là làm cho nó có thể thực thi được , chmod a+x ~/bin/gold/ld.

  3. Thay đổi các cuộc gọi của bạn gccthành gcc -B$HOME/bin/goldmà làm cho gcc trông trong thư mục nhất định cho các chương trình trợ giúp như thế ldvà do đó sử dụng tập lệnh keo thay vì mặc định của hệ thống ld.


1
Điều đó là cần thiết cho những gì hệ điều hành? Như nob đã nói trong câu trả lời của mình, đối với Ubuntu chỉ cần cài đặt gói binutils vàng và trình biên dịch sẽ sử dụng nó ngay lập tức. Tương tự đối với openSuse.
usr1234567

8
Có, khá dễ dàng để thay thế ld trên toàn hệ thống. Câu trả lời của tôi đặc biệt hướng đến cách sử dụng vàng có chọn lọc. Và trong trường hợp đó, tôi nghĩ, nó cần thiết cho bất kỳ hệ điều hành nào.
Tilman Vogel

1
@vidstige Có, ưu điểm của tập lệnh là nó tìm kiếm goldtrên PATH. Đối với một liên kết tượng trưng, ​​bạn cần phải trỏ đến đường dẫn đầy đủ.
Tilman Vogel

17

Gcc / g ++ có thể gọi trực tiếp vàng không.?

Chỉ để bổ sung cho các câu trả lời: có một tùy chọn của gcc -fuse-ld=gold(xem gcc doc ). Mặc dù AFAIK, có thể định cấu hình gcc trong quá trình xây dựng theo cách mà tùy chọn sẽ không có bất kỳ tác dụng nào.


5
-fuse-ld=goldnó chưa hoàn thiện. Nếu bạn phải sử dụng -Wl,-fuse-ld=goldvì nó được sử dụng tại thời điểm liên kết.
Nawaz

6
@Nawaz Không, -Wl,được sử dụng để chuyển trực tiếp một tùy chọn đến ld; để sử dụng một trình liên kết khác, bạn cần cho biết điều đó gcc. Vui lòng tham khảo tài liệu .
calandoa

11

Là một nhà phát triển Samba, tôi đã sử dụng trình liên kết vàng hầu như chỉ trên Ubuntu, Debian và Fedora kể từ vài năm nay. Đánh giá của tôi:

  • vàng nhanh hơn nhiều lần (phớt: 5-10 lần) so với trình liên kết cổ điển.
  • Ban đầu, có một vài vấn đề xảy ra, nhưng chúng đã biến mất kể từ phiên bản Ubuntu 12.04.
  • Trình liên kết vàng thậm chí còn tìm thấy một số vấn đề phụ thuộc trong mã của chúng tôi, vì nó có vẻ đúng hơn so với mã cổ điển về một số chi tiết. Hãy xem, ví dụ như cam kết Samba này .

Tôi đã không sử dụng vàng một cách chọn lọc, nhưng đã sử dụng liên kết tượng trưng hoặc cơ chế lựa chọn thay thế nếu bản phân phối cung cấp nó.


9

Bạn có thể liên kết ldđến gold(trong thư mục nhị phân cục bộ nếu bạn đã ldcài đặt để tránh ghi đè):

ln -s `which gold` ~/bin/ld

hoặc là

ln -s `which gold` /usr/local/bin/ld

5

Điểm chuẩn tổng hợp tối thiểu: LD vs vàng vs LLVM LLD

Kết quả:

  • vàng nhanh hơn khoảng 3 đến 4 lần đối với tất cả các giá trị tôi đã thử khi sử dụng -Wl,--threads -Wl,--thread-count=$(nproc)để kích hoạt đa luồng
  • LLD nhanh hơn vàng khoảng gấp đôi!

Đã thử nghiệm trên:

  • Ubuntu 20.04, GCC 9.3.0, binutils 2.34, sudo apt install lldLLD 10
  • Máy tính xách tay Lenovo ThinkPad P51, CPU Intel Core i7-7820HQ (4 nhân / 8 luồng), RAM 2x Samsung M471A2K43BB1-CRC (2x 16GiB), SSD Samsung MZVLB512HAJQ-000L7 (3.000 MB / s).

Mô tả đơn giản về các thông số điểm chuẩn:

  • 1: số tệp đối tượng cung cấp ký hiệu
  • 2: số lượng ký hiệu trên mỗi tệp đối tượng nhà cung cấp ký hiệu
  • 3: số tệp đối tượng sử dụng tất cả các ký hiệu biểu tượng được cung cấp

Kết quả cho các thông số điểm chuẩn khác nhau:

10000 10 10
nogold:  wall=4.35s user=3.45s system=0.88s 876820kB
gold:    wall=1.35s user=1.72s system=0.46s 739760kB
lld:     wall=0.73s user=1.20s system=0.24s 625208kB

1000 100 10
nogold:  wall=5.08s user=4.17s system=0.89s 924040kB
gold:    wall=1.57s user=2.18s system=0.54s 922712kB
lld:     wall=0.75s user=1.28s system=0.27s 664804kB

100 1000 10
nogold:  wall=5.53s user=4.53s system=0.95s 962440kB
gold:    wall=1.65s user=2.39s system=0.61s 987148kB
lld:     wall=0.75s user=1.30s system=0.25s 704820kB

10000 10 100
nogold:  wall=11.45s user=10.14s system=1.28s 1735224kB
gold:    wall=4.88s user=8.21s system=0.95s 2180432kB
lld:     wall=2.41s user=5.58s system=0.74s 2308672kB

1000 100 100
nogold:  wall=13.58s user=12.01s system=1.54s 1767832kB
gold:    wall=5.17s user=8.55s system=1.05s 2333432kB
lld:     wall=2.79s user=6.01s system=0.85s 2347664kB

100 1000 100
nogold:  wall=13.31s user=11.64s system=1.62s 1799664kB
gold:    wall=5.22s user=8.62s system=1.03s 2393516kB
lld:     wall=3.11s user=6.26s system=0.66s 2386392kB

Đây là tập lệnh tạo tất cả các đối tượng cho các bài kiểm tra liên kết:

tạo-đối tượng

#!/usr/bin/env bash
set -eu

# CLI args.

# Each of those files contains n_ints_per_file ints.
n_int_files="${1:-10}"
n_ints_per_file="${2:-10}"

# Each function adds all ints from all files.
# This leads to n_int_files x n_ints_per_file x n_funcs relocations.
n_funcs="${3:-10}"

# Do a debug build, since it is for debug builds that link time matters the most,
# as the user will be recompiling often.
cflags='-ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic'

# Cleanup previous generated files objects.
./clean

# Generate i_*.c, ints.h and int_sum.h
rm -f ints.h
echo 'return' > int_sum.h
int_file_i=0
while [ "$int_file_i" -lt "$n_int_files" ]; do
  int_i=0
  int_file="${int_file_i}.c"
  rm -f "$int_file"
  while [ "$int_i" -lt "$n_ints_per_file" ]; do
    echo "${int_file_i} ${int_i}"
    int_sym="i_${int_file_i}_${int_i}"
    echo "unsigned int ${int_sym} = ${int_file_i};" >> "$int_file"
    echo "extern unsigned int ${int_sym};" >> ints.h
    echo "${int_sym} +" >> int_sum.h
    int_i=$((int_i + 1))
  done
  int_file_i=$((int_file_i + 1))
done
echo '1;' >> int_sum.h

# Generate funcs.h and main.c.
rm -f funcs.h
cat <<EOF >main.c
#include "funcs.h"

int main(void) {
return
EOF
i=0
while [ "$i" -lt "$n_funcs" ]; do
  func_sym="f_${i}"
  echo "${func_sym}() +" >> main.c
  echo "int ${func_sym}(void);" >> funcs.h
  cat <<EOF >"${func_sym}.c"
#include "ints.h"

int ${func_sym}(void) {
#include "int_sum.h"
}
EOF
  i=$((i + 1))
done
cat <<EOF >>main.c
1;
}
EOF

# Generate *.o
ls | grep -E '\.c$' | parallel --halt now,fail=1 -t --will-cite "gcc $cflags -c -o '{.}.o' '{}'"

GitHub ngược dòng .

Lưu ý rằng việc tạo tệp đối tượng có thể khá chậm, vì mỗi tệp C có thể khá lớn.

Cho một đầu vào kiểu:

./generate-objects [n_int_files [n_ints_per_file [n_funcs]]]

nó tạo ra:

C chính

#include "funcs.h"

int main(void) {
    return f_0() + f_1() + ... + f_<n_funcs>();
}

f_0.c, f_1.c, ..., f_<n_funcs>.c

extern unsigned int i_0_0;
extern unsigned int i_0_1;
...
extern unsigned int i_1_0;
extern unsigned int i_1_1;
...
extern unsigned int i_<n_int_files>_<n_ints_per_file>;

int f_0(void) {
    return
    i_0_0 +
    i_0_1 +
    ...
    i_1_0 +
    i_1_1 +
    ...
    i_<n_int_files>_<n_ints_per_file>
}

0.c, 1.c, ..., <n_int_files>.c

unsigned int i_0_0 = 0;
unsigned int i_0_1 = 0;
...
unsigned int i_0_<n_ints_per_file> = 0;

dẫn đến:

n_int_files x n_ints_per_file x n_funcs

các vị trí trên liên kết.

Sau đó, tôi so sánh:

gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic               -o main *.o
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -fuse-ld=gold -Wl,--threads -Wl,--thread-count=`nproc` -o main *.o
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -fuse-ld=lld  -o main *.o

Một số giới hạn tôi đã cố gắng giảm thiểu khi chọn các thông số kiểm tra:

  • ở 100k tệp C, đôi khi cả hai phương pháp đều gặp lỗi mallocs
  • GCC không thể biên dịch một hàm với 1M bổ sung

Tôi cũng đã quan sát thấy mức 2x trong bản dựng gỡ lỗi của gem5: https://gem5.googlesource.com/public/gem5/+/fafe4e80b76e93e3d0d05797904c19928587f5b5

Câu hỏi tương tự: /unix/545699/what-is-the-gold-linker

Điểm chuẩn của phoronix

Phoronix đã thực hiện một số điểm chuẩn vào năm 2017 cho một số dự án trong thế giới thực, nhưng đối với các dự án mà họ đã kiểm tra, lợi nhuận vàng không quá đáng kể: https://www.phoronix.com/scan.php?page=article&item=lld4-linux-tests&num = 2 ( lưu trữ ).

Điểm không tương thích đã biết



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.