
나는 할 수 있다는 것을 안다Linux 파일 시스템 캐시에서 모든 것을 삭제하십시오., 하지만 특정 파일 하나만 삭제하는 방법이 있나요? 아니면 파일이 캐시되지 않도록 하시겠습니까? 아니면 프로세스가 작성한 파일을 캐시하지 않도록 지시하시겠습니까?
많은 작은 파일을 읽고 큰 파일을 쓰는 프로세스가 있습니다. 디스크 탐색을 피하기 위해 작은 파일을 캐시에 보관하고 싶고 큰 파일을 캐시하는 데는 신경 쓰지 않습니다.
답변1
잠재적인 방법 #1 - F_DROP_CACHES
나는 이 메일 스레드에서 Linux 커널에 대한 제안된 패치를 논의하는 2012년의 방법을 발견했습니다.Re: [RFC 패치] fs: 파일별 삭제 캐시 구현.
발췌Cong> 파일별 드롭 캐시를 구현하는 초안 패치입니다.
흥미로운. 그러면 프로세스 외부에서 이 작업을 수행할 수 있습니까? 저는 SysAdmin이므로 시스템에 압력이 가해졌을 때 성능 문제를 알아차리고 찾아 해결하는 것이 POV입니다.
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.
파일이 얼마나 많은 캐시를 사용하는지 어떻게 알 수 있나요? 사용량이 많은 시스템에서 실행될 때 성능에 어떤 영향을 미치나요? 그리고 시스템이 메모리 압력을 받으면 VM이 이미 캐시를 삭제해야 한다고 생각하기 때문에 이 패치가 우리에게 무엇을 제공합니까?
Cong> 아래는 이번 패치에 대한 작은 테스트 케이스입니다.
스레드에는 Linux 커널 내의 여러 파일에 대한 테스트 케이스와 실제 패치가 모두 포함되어 있습니다 fs/drop_caches.c
. drop_pagecache_file(struct file *filp)
이 기능은 프런트엔드 도구의 fnctl.c
명령을 통해 액세스할 수 있습니다 F_DROP_CACHES
. 이 경우에는 다음 함수를 호출합니다.
file_drop_caches(filp, arg);
주어진 파일과 관련된 모든 캐시 삭제를 처리합니다. 파일에서 include/linux/mm.h
:
void file_drop_caches(struct file *filp, unsigned long which);
그럼 이게 사용될 수 있는 걸까요?
이 패치가 기본 Linux 커널 코드 저장소에 적용되었다는 증거를 찾지 못했기 때문에 이 옵션은 Linux 커널을 직접 다시 컴파일하려는 경우에만 사용할 수 있는 것으로 보입니다.
잠재적인 방법 #2 - dd 사용
동일한 스레드에서 다른 사용자는 dd
.
테스트해 보세요유용한 기능입니다. 이미 제공되지 않았습니까
해당 패치의 예는 다음과 같습니다.POSIX_FADV_DONTNEED
? 이 기능이 추가되었습니다.GNU dd (8.11) 1년 전.
전체 파일에 대해 캐시를 삭제하도록 조언
$ dd if=ifile iflag=nocache count=0
전체 파일에 대한 캐시 삭제 보장
$ dd of=ofile oflag=nocache conv=notrunc,fdatasync count=0
파일 일부에 대한 캐시 삭제
$ dd if=ifile iflag=nocache skip=10 count=10 of=/dev/null
미리 읽기 캐시만 사용하여 데이터 스트리밍
$ dd if=ifile of=ofile iflag=nocache oflag=nocache
나는 이것을 테스트하는 방법을 100% 확신하지는 않았지만 다음과 같은 접근 방식을 생각해 냈습니다.
100MB 파일을 만드세요
$ dd if=/dev/urandom of=sample.txt bs=100M count=1
다음을 사용하여 추적 파일에 액세스합니다.
fatrace
$ sudo fatrace | grep sample.txt
실행
top
하면 메모리 사용량, 메모 양을 모니터링할 수 있습니다.$ top
파일을 열고 지금 사용 가능한 메모리 양을 기록해 두세요.
fatrace
파일의 을 참고하세요sample.txt
.$ cat sample.txt > /dev/null
메모리에서 파일을 삭제하고 지금 사용 가능한 메모리 양을 기록해 두십시오. 의 출력을 참고하십시오
fatrace
.$ sudo dd of=/home/saml/tst/162600/sample.txt \ oflag=nocache conv=notrunc,fdatasync count=0
예
터미널 #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
터미널 #2에서:
$ top
...
KiB Mem: 7968336 total, 6900956 used, 1067380 free, 267080 buffers
...
터미널 #3에서:
$ sudo fatrace | grep sample.txt
이제 파일을 열고 sample.txt
RAM 용량을 확인합니다. 터미널 1번에서.
$ cat sample.txt > /dev/null
터미널 #2에서:
KiB Mem: 7968336 total, 7011896 used, 956440 free, 267336 buffers
fatrace
터미널 #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
이제 터미널 #4의 RAM에서 파일을 제거합니다.
$ sudo dd of=/home/saml/tst/162600/sample.txt \
oflag=nocache conv=notrunc,fdatasync count=0
fatrace
터미널 #2 의 출력에 유의하세요 .
dd(26229): O /home/saml/tst/162600/sample.txt
dd(26229): CW /home/saml/tst/162600/sample.txt
터미널 #3의 RAM을 확인하세요.
KiB Mem: 7968336 total, 6908364 used, 1059972 free, 267364 buffers
따라서 RAM의 파일이 소비한 모든 것이 해제된 것처럼 보입니다.
잠재적인 방법 #3 - python-fadvise
@frostchutz의 의견 덕분에 [pyadvise][4]
위의 방법보다 훨씬 간단한 인터페이스를 제공하는 Python 스크립트라는 또 다른 도구가 있습니다 dd
. 이 스크립트는 동일한 posix_fadvise(2)
인터페이스를 사용합니다.
$ 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
pyadvise
그리고 위의 테스트를 반복하고 다음 대신 사용하면 dd
:
$ pyadvise -d /home/saml/tst/162600/sample.txt
.dd
답변2
O_DIRECT
@geekosaur의 답변을 확장하면 여기에서 LD_PRELOAD 및 프로그램을 사용하여 강제로 사용할 수 있습니다 .http://arighi.blogspot.com/2007/04/how-to-bypass-buffer-cache-in-linux.html
해당 코드는 O_DIRECT
모든 파일에 적용됩니다. 그러나 간단히 strncmp 로직을 추가하면 __do_wrap_open
O_DIRECT를 선택적으로 적용할 수 있습니다.
면책 조항: 나는 이것을 테스트하지 않았습니다.
답변3
플래그를 사용하여 개별 파일을 열 수 있습니다 O_DIRECT
( 참조 man 2 open
).노트해당 맨페이지 섹션을 주의 깊게 살펴보고 O_SYNC
.
답변4
파일이 항상 O_SYNC를 사용하도록 하려면 다음을 사용하여 확장 속성에서 이를 표시할 수 있습니다 chattr +S $file
.
남자 채팅:
'S' 속성이 설정된 파일이 수정되면 변경 사항이 디스크에 동기적으로 기록됩니다. 이는 파일의 하위 집합에 적용되는 '동기화' 마운트 옵션과 동일합니다.
O_SYNC는 데이터+메타데이터를 디스크 버퍼에 강제로 기록하지만 여전히 페이지 캐시를 통과합니다. O_DIRECT는 페이지 캐시를 우회합니다.
그러나 O_DIRECT로 열면 성능에 해로울 수 있다는 점에 유의하십시오. 큰 파일이 추가되는 경우 차이가 작을 수 있습니다. 그러나 큰 파일이 임의의 위치에 다시 작성되면 O_DIRECT는 성능에 매우 큰 타격을 줄 것입니다. 심지어 캐시에 파일이 있으면 작은 읽기 파일 중 일부가 캐시에서 제거될 수 있다는 점을 고려하더라도 마찬가지입니다.
작은 파일을 모두 보관할 수 있는 RAM이 있다면 다른 방식으로 문제에 접근할 수 있습니다. 작은 파일이 항상 RAM에 있는지 확인한 다음 해당 파일을 RAM에 복사하는 것이 좋습니다.tmpfs:
tmpfs는 모든 것을 커널 내부 캐시에 저장하고 포함된 파일을 수용할 수 있도록 확장 및 축소합니다.