У меня есть программа, которая открывает большое количество файлов. Я планирую выполнение цикла C ++, который буквально просто открывает и закрывает файлы, используя таймер C ++ и strace. Как ни странно, системное время и время, регистрируемое C ++ (которые согласуются друг с другом), на несколько порядков больше, чем время, затрачиваемое на проверку временных ограничений в системных вызовах. Как это может быть? Я поставил источник и вывод ниже.
Все это произошло потому, что я обнаружил, что мое приложение тратит неоправданно много времени только на открытие файлов. Чтобы помочь мне определить проблему, я написал следующий тестовый код (для справки файл «files.csv» — это просто список с одним путем к файлу в строке):
#include <stdio.h>
#include...
using namespace std;
int main(){
timespec start, end;
ifstream fin("files.csv");
string line;
vector<string> files;
while(fin >> line){
files.push_back(line);
}
fin.close();
clock_gettime(CLOCK_MONOTONIC, &start);
for(int i=0; i<500; i++){
size_t filedesc = open(files[i].c_str(), O_RDONLY);
if(filedesc < 0) printf("error in open");
if(close(filedesc)<0) printf("error in close");
}
clock_gettime(CLOCK_MONOTONIC, &end);
printf(" %fs elapsed\n", (end.tv_sec-start.tv_sec) + ((float)(end.tv_nsec - start.tv_nsec))/1000000000);
return 0;
}
И вот что я получаю, когда запускаю его:
-bash$ time strace -ttT -c ./open_stuff
5.162448s elapsed <------ Output from C++ code
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
99.72 0.043820 86 508 open <------output from strace
0.15 0.000064 0 508 close
0.14 0.000061 0 705 read
0.00 0.000000 0 1 write
0.00 0.000000 0 8 fstat
0.00 0.000000 0 25 mmap
0.00 0.000000 0 12 mprotect
0.00 0.000000 0 3 munmap
0.00 0.000000 0 52 brk
0.00 0.000000 0 2 rt_sigaction
0.00 0.000000 0 1 rt_sigprocmask
0.00 0.000000 0 1 1 access
0.00 0.000000 0 1 execve
0.00 0.000000 0 1 getrlimit
0.00 0.000000 0 1 arch_prctl
0.00 0.000000 0 3 1 futex
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 1 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 0.043945 1834 2 total
real 0m5.821s <-------output from time
user 0m0.031s
sys 0m0.084s
Теоретически сообщаемое «истекшее» время из C ++ должно быть временем выполнения вызовов open (2) плюс минимальные накладные расходы на выполнение цикла for 500 раз. И все же сумма общего времени в вызовах open (2) и close (1) от strace на 99% короче. Я не могу понять, что происходит.
PS Разница между затраченным временем и системным временем связана с тем, что файл files.csv на самом деле содержит десятки тысяч путей, которые все загружаются.
Сравнивать прошедшее время со временем исполнения — все равно что сравнивать яблоки с апельсиновым соком. (Один из них пропускает целлюлозу :)) Чтобы открыть файл, система должна найти и прочитать соответствующую запись в каталоге … и, если пути глубокие, может потребоваться перераспределить количество записей в каталоге. Если записи не кэшируются, их необходимо будет прочитать с диска, что потребует поиска диска. Пока головки дисков движутся, а сектор вращается вокруг того места, где находятся головки дисков, настенные часы продолжают тикать, но процессор может делать другие вещи (если есть над чем работать). Так что это считается прошедшим временем — тикают неумолимые часы — но не время исполнения.
Других решений пока нет …