Thả một tập tin cụ thể từ bộ đệm hệ thống tập tin Linux?


23

Tôi biết tôi có thể loại bỏ mọi thứ từ bộ đệm của hệ thống tệp Linux , nhưng có cách nào để bỏ chỉ một tệp cụ thể không? Hoặc ngăn chặn một tập tin được lưu trữ? Hoặc nói một quá trình không lưu trữ bất kỳ tập tin nào nó ghi?

Tôi có một quá trình đọc rất nhiều tệp nhỏ và viết một tệp lớn. Tôi muốn giữ các tệp nhỏ trong bộ đệm để tránh tìm kiếm đĩa và tôi không quan tâm đến việc lưu tệp lớn.


1
Về tiền thưởng, tôi đặc biệt quan tâm đến câu hỏi tiêu đề: bỏ một tệp cụ thể khỏi bộ đệm (trái ngược với việc ngăn không cho nó đến đó ngay từ đầu).
Gilles 'SO- ngừng trở nên xấu xa'

Câu trả lời:


21

Phương pháp tiềm năng số 1 - F_DROP_CACHES

Tôi đã tìm thấy một phương pháp từ năm 2012 thảo luận về một bản vá được đề xuất cho nhân Linux trong chuỗi thư này có tiêu đề: Re: [RFC Patch] fs: hiện thực hiện bộ đệm thả trên mỗi tệp .

đoạn trích

Cong> Đây là một bản vá dự thảo về việc thực hiện bộ đệm thả trên mỗi tệp.

Hấp dẫn. Vì vậy, tôi có thể làm điều này từ bên ngoài một quá trình? Tôi là một SysAdmin, vì vậy POV của tôi không chú ý, tìm và khắc phục các sự cố về hiệu suất khi hệ thống chịu áp lực.

Cong> It introduces a new fcntl command  F_DROP_CACHES to drop  
Cong> file caches of a specific file. The reason is that currently  
Cong> we only have a system-wide drop caches interface, it could  
Cong> cause system-wide performance down if we drop all page caches  
Cong> when we actually want to drop the caches of some huge file.

Làm thế nào tôi có thể biết bao nhiêu bộ đệm được sử dụng bởi một tập tin? Và tác động hiệu suất của việc này khi chạy trên một hệ thống bận rộn là gì? Và bản vá này mua gì cho chúng tôi vì tôi nghĩ VM nên bỏ bộ nhớ cache một khi hệ thống chịu áp lực mem ...

Cong> Dưới đây là trường hợp thử nghiệm nhỏ cho bản vá này:

Chuỗi này bao gồm cả một testcase và bản vá thực tế cho một số tệp trong nhân Linux, có thêm một chức năng bổ sung để fs/drop_caches.cgọi drop_pagecache_file(struct file *filp). Chức năng này sau đó có thể truy cập thông qua công cụ frontend, fnctl.cthông qua lệnh F_DROP_CACHES. Trường hợp này gọi chức năng này:

file_drop_caches(filp, arg);

Mà xử lý việc bỏ tất cả các bộ nhớ cache liên quan đến tập tin đã cho. Từ tệp include/linux/mm.h:

void file_drop_caches(struct file *filp, unsigned long which);
Vì vậy, điều này có thể được sử dụng?

Tôi không tìm thấy bằng chứng nào cho thấy bản vá này từng được đưa vào kho lưu trữ mã nhân Linux chính, vì vậy tùy chọn này sẽ xuất hiện, chỉ khi bạn sẵn sàng tự biên dịch lại nhân Linux.

Phương pháp tiềm năng số 2 - Sử dụng dd

Trong cùng một chủ đề, một người dùng khác đề cập đến một phương pháp hoàn toàn khác sử dụng dd.

Sau đây là đoạn trích từ email đó

Đây là chức năng hữu ích. Mặc dù nó không được cung cấp POSIX_FADV_DONTNEED? Chức năng này đã được thêm vào GNU dd (8.11) một năm trước .

Dưới đây là các ví dụ từ bản vá đó:
  • Khuyên bạn nên bỏ cache cho toàn bộ tập tin

     $ dd if=ifile iflag=nocache count=0
    
  • Đảm bảo thả bộ đệm cho toàn bộ tệp

     $ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
    
  • Thả bộ đệm cho một phần của tập tin

     $ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
    
  • Truyền dữ liệu chỉ bằng bộ đệm đọc trước

     $ dd if=ifile of=ofile iflag=nocache oflag=nocache
    
Kiểm tra nó ra

Tôi đã không tích cực 100% làm thế nào để kiểm tra điều này nhưng tôi đã đưa ra cách tiếp cận sau.

  1. tạo một tệp 100 MB

    $ dd if=/dev/urandom of=sample.txt bs=100M count=1
    
  2. truy cập tệp theo dõi bằng cách sử dụng fatrace

    $ sudo fatrace | grep sample.txt
    
  3. chạy topđể chúng tôi có thể theo dõi việc sử dụng bộ nhớ, ghi chú số lượng miễn phí.

    $ top
    
  4. mở tập tin, lưu ý số lượng bộ nhớ miễn phí bây giờ. Lưu ý fatracecác tập tin sample.txt.

    $ cat sample.txt > /dev/null
    
  5. thả tập tin từ bộ nhớ, lưu ý số lượng bộ nhớ trống ngay bây giờ. Lưu ý đầu ra của fatrace.

    $ sudo dd of=/home/saml/tst/162600/sample.txt \
        oflag=nocache conv=notrunc,fdatasync count=0
    

Thí dụ

Trong thiết bị đầu cuối số 1:
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
1+0 records in
1+0 records out
104857600 bytes (105 MB) copied, 7.37996 s, 14.2 MB/s

$ ls -l sample.txt 
-rw-rw-r--. 1 saml saml 104857600 Oct 17 22:54 sample.txt
Trong thiết bị đầu cuối số 2:
$ top
...
KiB Mem:   7968336 total,  6900956 used,  1067380 free,   267080 buffers
...
Trong thiết bị đầu cuối số 3:
$ sudo fatrace | grep sample.txt
Bây giờ hãy mở tệp sample.txtvà lưu ý dung lượng RAM. Trong thiết bị đầu cuối # 1.
$ cat sample.txt > /dev/null
Trong thiết bị đầu cuối số 2:
KiB Mem:   7968336 total,  7011896 used,   956440 free,   267336 buffers
Lưu ý đầu ra của fatracethiết bị đầu cuối số 3:
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): R /home/saml/tst/162600/sample.txt
cat(25940): RC /home/saml/tst/162600/sample.txt
Bây giờ xóa tệp khỏi RAM, trong thiết bị đầu cuối # 4:
$ sudo dd of=/home/saml/tst/162600/sample.txt \
    oflag=nocache conv=notrunc,fdatasync count=0
Lưu ý đầu ra của fatracethiết bị đầu cuối # 2:
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
Lưu ý RAM trong thiết bị đầu cuối # 3:
KiB Mem:   7968336 total,  6908364 used,  1059972 free,   267364 buffers

Vì vậy, dường như tất cả những gì được sử dụng bởi tệp trong RAM đều được giải phóng.

Phương pháp tiềm năng # 3 - python-fadvise

Nhờ nhận xét của @frostchutz, có một công cụ khác, tập lệnh Python, được đặt tên [pyadvise][4]cung cấp giao diện đơn giản hơn nhiều so với các ddphương thức trên . Kịch bản này sử dụng cùng một posix_fadvise(2)giao diện.

Thí dụ
$ sudo pyadvise --help
Usage: 
    pyadvise [options] [FILE]..

Options:
  -h, --help        show this help message and exit
  -w, --willneed    The specified files will be accessed in the near future
  -s, --sequential  The application expects to access the specified files
                    sequentially (with lower offsets read before higher ones)
  -d, --dontneed    The specified files will not be accessed in the near
                    future
  -r, --random      The specified files will be accessed in random order
  -o, --noreuse     The specified files will be accessed only once. Under
                    Linux, this operation is a no-op; see contrib/copyfileobj-
                    fadvise.py in the python-fadvise source tree for an
                    example on how to achieve approximately the same effect
  -n, --normal      Indicates that the application has no advice to give about
                    its access pattern for the specified files. If no advice
                    is given for an open file, this is the default assumption
  -v, --verbose     Explain what is being done

Và nếu chúng tôi lặp lại thử nghiệm trên và sử dụng pyadvisethay cho dd:

$ pyadvise -d /home/saml/tst/162600/sample.txt

Tôi nhận thấy sự sụt giảm RAM giống hệt nhau được tiêu thụ như trước đây khi tôi sử dụng dd.


ddlàm việc cho tôi Tôi đã kết thúc với chris-lamb.co.uk/projects/python-fadvise bản thân tôi, đó là điều tương tự trong một lệnh rõ ràng hơn.
frostschutz

@frostschutz - rất tuyệt. Tôi đã không nghe về điều này cho đến khi Gilles hỏi liệu có ai biết làm điều này trong trò chuyện không. python-fadvisedễ dàng hơn nhiều, tôi đã thêm một ví dụ hiển thị dd.
slm

Liên kết cho tập lệnh python nên được chuyển vào phần chính của câu hỏi. Bình luận có thể biến mất không dấu vết. Một chỉnh sửa sẽ tồi tệ nhất vẫn còn trong lịch sử. Phải nói rằng, một tìm kiếm Google tìm thấy nó dễ dàng, vì vậy không phải là một vấn đề lớn.
Faheem Mitha

Nó thậm chí dường như hoạt động mà không có sudo, vì vậy bất cứ ai có thể xem một tệp (ngay cả khi không có quyền ghi) đều có thể xóa bộ nhớ cache, điều đó thật ... thú vị.
frostschutz

1
Bây giờ có os.posix_fadvise()trong thư viện tiêu chuẩn của Python.
kawing-chiu

3

Mở rộng câu trả lời của @ geekizard, bạn có thể buộc sử dụng O_DIRECTbằng cách sử dụng LD_PRELOAD và chương trình tại đây: http://arighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html

Mã đó buộc O_DIRECTcho tất cả các tập tin. Tuy nhiên, chỉ cần thêm một số logic strncmp trong __do_wrap_openbạn có thể áp dụng có chọn lọc O_DIRECT.

Tuyên bố miễn trừ trách nhiệm: Tôi chưa thử nghiệm điều này.


2

Bạn có thể mở các tệp riêng lẻ bằng O_DIRECTcờ (xem man 2 open) - đọc phần LƯU Ý của trang đó một cách cẩn thận và xem xét liệu bạn cũng muốn / cần hay không O_SYNC.


1
Vâng, quá trình của tôi là cat, và tôi không muốn viết lại nó. :) Tôi đã hy vọng cho một công cụ dòng lệnh hoặc /proc/sysnúm.
Jay Hacker

2
Tệ hơn thế, tôi nghi ngờ bạn thực sự có nghĩa là bạn đang sử dụng chuyển hướng, vì vậy quy trình của bạn là vỏ. Tôi không biết cách mỗi tệp để kiểm soát điều này ngoài opencờ; bạn thực sự sẽ cần phải viết một chương trình để làm điều đó. ( cat -uchỉ vô hiệu hóa stdiobộ đệm, không phải bộ đệm hệ điều hành.)
geekizard

-2

Nếu bạn muốn buộc một tệp luôn sử dụng O_SYNC, bạn có thể đánh dấu nó như vậy trong các thuộc tính mở rộng với chattr +S $file:

người đàn ông chattr:

Khi một tệp có tập thuộc tính 'S' được sửa đổi, các thay đổi được ghi đồng bộ trên đĩa; điều này tương đương với tùy chọn gắn kết 'đồng bộ hóa' được áp dụng cho một tập hợp con của các tệp.

O_SYNC buộc dữ liệu + siêu dữ liệu được ghi vào bộ đệm đĩa, nhưng nó vẫn chuyển qua bộ đệm trang. O_DIRECT bỏ qua bộ đệm trang.

Nhưng hãy lưu ý rằng việc mở nó bằng O_DIRECT sẽ gây bất lợi cho hiệu suất, nếu tệp lớn nó chỉ được thêm vào thì sự khác biệt có thể nhỏ. Nhưng nếu tệp lớn, nó được viết lại ở những nơi ngẫu nhiên thì O_DIRECT sẽ là một thành công rất lớn đối với hiệu suất, thậm chí có tính đến việc nó có trong bộ đệm có thể có thể bị xóa khỏi bộ đệm một số tệp đọc nhỏ.

Nếu bạn có ram để giữ tất cả các tệp nhỏ ở đó, bạn có thể tiếp cận vấn đề theo cách khác. Đảm bảo rằng các tệp nhỏ luôn trong ram, sau đó tôi sẽ đề nghị sao chép chúng vào tmpfs :

tmpfs đặt mọi thứ vào bộ nhớ trong kernel và phát triển và thu nhỏ để chứa các tệp mà nó chứa


chattr +Skhông giống như O_DIRECT, nó giống như O_SYNC. O_DIRECTkhiến cho các lần đọc không được lưu vào bộ nhớ cache (đó là những gì câu hỏi này nói về) và viết không được đệm, không có bảo đảm. O_SYNCnguyên nhân chỉ viết không được đệm.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles bạn nói đúng, tôi đọc câu hỏi và nghĩ về việc xả dữ liệu vào đĩa như tôi đã làm trước đây. Và có một điều tinh tế khác, nhưng quan trọng trong trường hợp này, sự khác biệt giữa O_DIRECT và O_SYNC, O_DIRECT bỏ qua bộ đệm trang, nhưng O_SYNC thì không, nó buộc dữ liệu (và siêu dữ liệu) bị xóa vào đĩa, nhưng nó đi qua bộ đệm trang và được giữ ở đó để tăng tốc độ đọc. Tôi có nên thay đổi O_DIRECT cho O_SYNC trong câu trả lời của mình không để nó ở lại với một xác nhận sai?
Jorge Nerín

Câu hỏi này hỏi về việc giữ một tệp lớn mà nó đã được ghi ra khỏi bộ đệm. Tôi nghĩ rằng việc mở nó bằng O_DIRECT sẽ gây bất lợi cho hiệu suất và nếu tệp lớn thì nó chỉ được thêm vào, sự khác biệt có thể nhỏ. Nhưng nếu tệp lớn, nó được viết lại ở những nơi ngẫu nhiên thì O_DIRECT sẽ là một thành công lớn về hiệu suất, thậm chí có tính đến việc nó có thể bị đuổi khỏi bộ đệm một số tệp đọc nhỏ.
Jorge Nerín

Thay đổi O_DIRECTthành O_SYNCsẽ làm cho câu trả lời của bạn nhất quán trong nội bộ, nhưng vẫn sai khi xem xét câu hỏi.
Gilles 'SO- ngừng trở nên xấu xa'
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.