퓨즈 파일 시스템을 작성하는 동안 하드 드라이브의 읽기를 줄이기 위해 모두 파일 및 디렉토리로 시작하는 캐시로 unordered_map<std::string, struct stat>
을 캐시로 사용합니다. readdir()
콜백을 만족하려면경로 목록에서 디렉토리 목록을 최적화하는 방법은 무엇입니까?
나는 다음과 같은 루프를 썼다 :
const int sp = path == "/" ? 0 : path.size();
for (auto it = stat_cache.cbegin(); it != stat_cache.cend(); it++)
{
if (it->first.size() > sp)
{
int ls = it->first.find_last_of('/');
if (it->first.find(path, 0) == 0 && ls == sp)
filler(buf, it->first.substr(ls + 1).c_str(), const_cast<struct stat*>(&it->second), 0, FUSE_FILL_DIR_PLUS);
}
}
경로의 객체가 될 것이라고 디렉토리 경로의 끝에서 마지막 슬래시를 디렉토리 경로로 시작 데 있다는 것을 생각 그것의 일원. 나는 이것을 철저히 시험했으며 작동한다.
그림 :
Reading directory: /foo/bar
Candidate file: /bazboo/oof - not in dir (wrong prefix)
Candidate file: /foo/bar/baz/boo - not in dir (wrong lastslash location)
Candidate file: /foo/bar/baz - in dir!
지금, 그러나,이 (캐시에 백만 절반 이상 객체, 특히 파일 시스템에서) 놀라 울 정도로 느립니다. Valgrind/Callgrind는 특히 std::string:find_last_of()
과 std::string::find()
전화를 탓합니다.
루프 속도를 높이기 위해 if (it->first.size() > sp)
을 이미 추가했지만 성능 향상 효과는 미미했습니다.
또한이 루틴을 4 개의 청크로 병렬 처리하여 속도를 높이려고했으나 unordered_map::cbegin()
동안 segfault에서 종료되었습니다.
는 더 이상 실제 코드를 가지고 있지 않지만, 나는 이런 식으로 뭔가를보고 생각 :
const int sp = path == "/" ? 0 : path.size();
ThreadPool<4> tpool;
ulong cq = stat_cache.size()/4;
for (int i = 0; i < 4; i++)
{
tpool.addTask([&]() {
auto it = stat_cache.cbegin();
std::next(it, i * cq);
for (int j = 0; j < cq && it != stat_cache.cend(); j++, it++)
{
if (it->first.size() > sp)
{
int ls = it->first.find_last_of('/');
if (it->first.find(path, 0) == 0 && ls == sp)
filler(buf, it->first.substr(ls + 1).c_str(), const_cast<struct stat*>(&it->second), 0, FUSE_FILL_DIR_PLUS);
}
}
});
}
tpool.joinAll();
나는 또한 unordered_map::cbegin(int)
가 편리한 과부하를 제공하는지도 버킷하여 분할과 함께이 시도하지만, 여전히 segfaulted.
다시 말하지만, 저는 현재 첫 번째 (비 병렬) 코드로 작업 중이며 병렬 처리 된 코드가 작동하지 않으므로이 코드에 대한 도움이 필요합니다. 나는 단지 완성을위한 나의 평행 한 시도, 멍청한 행동과 노력의 증거를 포함시킬 것이라고 생각했다.
이 루프를 최적화하는 다른 옵션이 있습니까?
다른 방법으로 코드가 작동하고 속도/효율성을 위해 코드를 최적화하도록 요청하는 경우 대신 [CodeReview] (http://codereview.stackexchange.com)에 게시해야합니다. –
'unordered_map'이 아닌'map'을 사용하고, 디렉토리 이름을 'upper_bound'라고 부르면 O (lg N)의 첫 번째 항목을 찾은 다음 다른 항목은 모두 인접합니다. 'readdir'의 최종 비용 : O (k + lg N) –