Tổng quat
Câu hỏi này được cấu trúc như sau:
Trước tiên tôi đưa ra một số nền tảng về lý do tại sao tôi quan tâm đến chủ đề này và cách nó sẽ giải quyết vấn đề mà tôi đang giải quyết. Sau đó, tôi hỏi câu hỏi độc lập thực tế liên quan đến bộ nhớ đệm hệ thống tệp, vì vậy nếu bạn không quan tâm đến động lực (một số thiết lập xây dựng dự án C ++), chỉ cần bỏ qua phần đầu tiên.
Vấn đề ban đầu: Liên kết các thư viện dùng chung
Tôi đang tìm cách để tăng tốc thời gian xây dựng dự án của chúng tôi. Thiết lập như sau: Một thư mục (hãy gọi nó workarea
) được đặt trong một chia sẻ NFS. Nó ban đầu chỉ chứa mã nguồn và tệp thực hiện. Sau đó, quá trình xây dựng trước tiên tạo các thư viện tĩnh trong workarea/lib
và sau đó tạo các thư viện dùng chung workarea/dll
, sử dụng các thư viện tĩnh trong workarea/lib
. Trong quá trình tạo các thư viện dùng chung, chúng không chỉ được viết mà còn được đọc lại bằng cách sử dụng, vdnm
để xác minh tại thời điểm liên kết mà không có biểu tượng nào bị thiếu. Sử dụng song song nhiều công việc, (ví dụ: make -j 20 hoặc make -j 40), thời gian xây dựng nhanh chóng bị chi phối bởi thời gian liên kết. Trong trường hợp này, hiệu suất liên kết bị giới hạn bởi hiệu suất hệ thống tệp. Ví dụ: liên kết với 20 công việc song song mất khoảng 35 giây trong chia sẻ NFS, nhưng chỉ 5 giây trong ổ RAM. Lưu ý rằng việc sử dụng rsync để sao chép dll
lại vào chia sẻ NFS mất thêm 6 giây, do đó, làm việc trong ổ RAM và đồng bộ hóa với NFS sau đó nhanh hơn nhiều so với làm việc trực tiếp trong chia sẻ NFS. Tôi đang tìm cách để đạt được hiệu suất nhanh mà không cần sao chép / liên kết rõ ràng các tệp giữa chia sẻ NFS và ổ RAM.
Lưu ý rằng chia sẻ NFS của chúng tôi đã sử dụng bộ đệm, nhưng bộ đệm này chỉ có thể lưu trữ truy cập đọc.
AFAIK, NFS yêu cầu mọi máy khách NFS không được xác nhận ghi cho đến khi máy chủ NFS xác nhận hoàn thành ghi, do đó máy khách không thể sử dụng bộ đệm ghi cục bộ và thông lượng ghi bị giới hạn bởi tốc độ mạng. Điều này giới hạn hiệu quả thông lượng ghi kết hợp đến khoảng 80MB / s trong thiết lập của chúng tôi.
Hiệu suất đọc, tuy nhiên, tốt hơn nhiều, vì bộ đệm đọc được sử dụng. Nếu tôi thực hiện liên kết (tạo nội dung dll
) với workarea/lib
trong NFS và workarea/dll
là liên kết tượng trưng cho ổ RAM, hiệu suất vẫn tốt - khoảng 5 giây. Lưu ý rằng quá trình xây dựng là bắt buộc để kết thúc với việc workarea/*
cư trú trong chia sẻ NFS: lib
cần phải ở trong phần chia sẻ (hoặc bất kỳ gắn kết liên tục nào) để cho phép các bản dựng gia tăng nhanh vàdll
cần phải có trong NFS để được truy cập bởi các máy tính bắt đầu công việc bằng cách sử dụng các dll này.
Do đó, tôi muốn áp dụng một giải pháp cho vấn đề bên dưới workarea/dll
và cũng có thể workarea/lib
(cách sau để cải thiện thời gian biên dịch). Yêu cầu về thời gian thiết lập nhanh dưới đây là do sự cần thiết phải thực hiện các bản dựng gia tăng nhanh, chỉ sao chép dữ liệu nếu được yêu cầu.
Cập nhật
Tôi có lẽ nên có một chút cụ thể hơn về thiết lập xây dựng. Dưới đây là một số chi tiết: Các đơn vị biên dịch được biên dịch thành các tệp .o trong một thư mục tạm thời (in / tmp). Chúng sau đó được hợp nhất vào các thư viện tĩnh trong lib
việc sử dụng ar
. Quá trình xây dựng hoàn chỉnh là gia tăng:
- Các đơn vị biên dịch chỉ được biên dịch lại nếu chính đơn vị biên dịch (tệp .C) hoặc một tiêu đề đi kèm đã thay đổi (sử dụng các tệp phụ thuộc do trình biên dịch tạo vào
make
). - Thư viện tĩnh chỉ được cập nhật nếu một trong các đơn vị biên dịch của nó đã được biên dịch lại.
- Thư viện dùng chung chỉ được xem lại nếu một trong những thư viện tĩnh của nó đã thay đổi. Biểu tượng của các thư viện dùng chung chỉ được kiểm tra lại nếu các biểu tượng được cung cấp bởi các thư viện dùng chung, nó phụ thuộc vào sự thay đổi nếu chính thư viện chia sẻ đã được cập nhật.
Tuy nhiên, việc xây dựng lại hoàn chỉnh hoặc gần hoàn thành là khá thường xuyên, vì nhiều trình biên dịch ( gcc
, clang
), phiên bản trình biên dịch, chế độ biên dịch ( release
, debug
), tiêu chuẩn C ++ ( C++97
, C++11
) và sửa đổi bổ sung (ví dụ libubsan
) có thể được sử dụng. Tất cả các kết hợp sử dụng hiệu quả các thư mục lib
và dll
thư mục khác nhau , do đó, người ta có thể chuyển đổi giữa các thiết lập và xây dựng tăng dần dựa trên bản dựng cuối cùng cho chính thiết lập đó. Ngoài ra, đối với các bản dựng gia tăng, thường chỉ cần biên dịch lại một vài tệp, mất rất ít thời gian, nhưng kích hoạt lại các thư viện chia sẻ (có thể lớn), mất nhiều thời gian hơn.
Cập nhật 2
Trong thời gian chờ đợi, tôi đã tìm hiểu về nocto
tùy chọn gắn kết NFS, có vẻ như có thể giải quyết vấn đề của tôi về cơ bản tất cả các triển khai NFS ngoại trừ Linux, vì Linux luôn xóa bộ đệm close()
, ngay cả với nocto
. Chúng tôi đã thử một số thứ khác: Ví dụ: chúng tôi có thể sử dụng một máy chủ NFS cục bộ khác async
được kích hoạt làm bộ đệm ghi và xuất khung gắn NFS chính, nhưng thật không may, máy chủ NFS không có bộ đệm ghi trong trường hợp này. Có vẻ như điều đó async
chỉ có nghĩa là máy chủ không buộc hệ thống tệp bên dưới của nó chuyển sang lưu trữ ổn định và bộ đệm ghi được sử dụng ngầm trong trường hợp hệ thống tệp bên dưới sử dụng bộ đệm ghi (vì rõ ràng đó là trường hợp của hệ thống tệp trên ổ đĩa vật lý).
Chúng tôi thậm chí đã nghĩ về tùy chọn sử dụng máy ảo không phải Linux trên cùng một hộp gắn kết chia sẻ NFS chính bằng cách sử dụng nocto
, cung cấp bộ đệm ghi và cung cấp bộ đệm này thông qua một máy chủ NFS khác, nhưng chưa thử nghiệm và muốn tránh một giải pháp như vậy.
Chúng tôi cũng tìm thấy một số FUSE
trình bao bọc hệ thống tập tin dựa trên bộ đệm, nhưng không có bộ đệm ghi nào được triển khai.
Bộ nhớ đệm và đệm một thư mục
Hãy xem xét một số thư mục, hãy gọi nó orig
, nằm trong một hệ thống tệp chậm, ví dụ như chia sẻ NFS. Trong một khoảng thời gian ngắn (ví dụ giây hoặc phút, nhưng dù sao thì điều này cũng không quan trọng), tôi muốn tạo một chế độ xem được lưu trữ và lưu vào bộ đệm đầy đủ của orig
việc sử dụng một thư mục cache
, nằm trong một hệ thống tệp nhanh, ví dụ như ổ cứng cục bộ hoặc thậm chí là một Ổ đĩa RAM. Bộ nhớ cache phải được truy cập thông qua ví dụ một mount cached_view
và không yêu cầu quyền root. Tôi giả sử rằng trong suốt vòng đời của bộ đệm, không có quyền truy cập đọc hoặc ghi trực tiếp orig
(tất nhiên bên cạnh bộ đệm). Bằng cách lưu trữ đầy đủ và được lưu vào bộ đệm, tôi có nghĩa như sau:
- Các truy vấn đọc được trả lời bằng một lần chuyển tiếp truy vấn đến hệ thống tệp
orig
, lưu vào kết quả đó và sử dụng nó từ đó trở đi và - Các truy vấn ghi được ghi vào
cache
và xác nhận khi hoàn thành trực tiếp, tức là bộ đệm cũng là bộ đệm ghi. Điều này thậm chí sẽ xảy ra khiclose()
được gọi trên tập tin bằng văn bản. Sau đó, trong nền, ghi được chuyển tiếp (có thể sử dụng hàng đợi) đếnorig
. Đọc các truy vấn đến dữ liệu bằng văn bản được trả lời bằng cách sử dụng dữ liệu trongcache
, tất nhiên.
Hơn nữa, tôi cần:
- Bộ đệm cung cấp một chức năng để tắt bộ đệm, giúp xóa tất cả ghi vào
orig
. Thời gian xả chỉ nên phụ thuộc vào kích thước của tệp được viết chứ không phải tất cả các tệp. Sau đó, người ta có thể truy cập một cách an toànorig
. - Thời gian thiết lập nhanh, ví dụ: khởi tạo bộ đệm chỉ có thể phụ thuộc vào số lượng tệp trong
orig
, chứ không phụ thuộc vào kích thước tệporig
, vì vậy sao chéporig
vàocache
một lần không phải là một tùy chọn.
Cuối cùng, tôi cũng sẽ ổn với một giải pháp không sử dụng hệ thống tệp khác làm bộ đệm, mà chỉ lưu trữ trong bộ nhớ chính (các máy chủ có nhiều RAM). Lưu ý rằng việc sử dụng bộ đệm dựng sẵn của ví dụ NFS không phải là một tùy chọn, vì AFAIK NFS không cho phép ghi bộ đệm (phần đầu tiên của cf).
Trong thiết lập của mình, tôi có thể mô phỏng một hành vi tồi tệ hơn một chút bằng cách liên kết nội dung của orig
đến cache
, sau đó làm việc với cache
(vì tất cả các thao tác ghi thực sự thay thế các tệp bằng các tệp mới, trong trường hợp đó, các liên kết tượng trưng được thay thế bằng các phiên bản cập nhật) và kết nối sửa đổi tập tin để orig
sau đó. Điều này không đáp ứng chính xác các yêu cầu ở trên, ví dụ: việc đọc chỉ được thực hiện một lần và các tệp được thay thế bằng liên kết tượng trưng, điều này tất nhiên sẽ tạo ra sự khác biệt cho một số ứng dụng.
Tôi cho rằng đây không phải là cách chính xác để giải quyết vấn đề này (ngay cả trong cài đặt đơn giản hơn của tôi) và có thể ai đó biết về giải pháp sạch hơn (và nhanh hơn!).
cachefilesd
có thể làm tốt hơn?