![`/usr/share/dict/words` 복사본을 읽는 것은 파일 자체보다 10배 느립니다.](https://linux55.com/image/197365/%60%2Fusr%2Fshare%2Fdict%2Fwords%60%20%EB%B3%B5%EC%82%AC%EB%B3%B8%EC%9D%84%20%EC%9D%BD%EB%8A%94%20%EA%B2%83%EC%9D%80%20%ED%8C%8C%EC%9D%BC%20%EC%9E%90%EC%B2%B4%EB%B3%B4%EB%8B%A4%2010%EB%B0%B0%20%EB%8A%90%EB%A6%BD%EB%8B%88%EB%8B%A4..png)
저는 C로 사전을 구현하려고 하는데 /usr/share/dict/words
이것이 테스트하기에 좋은 파일이라는 것을 알았습니다. 어떤 이유에서든 파일이라는 단어를 작업 디렉토리에 복사하고 싶었지만 놀랍게도 프로그램이 파일을 읽는 속도가 상당히 느려졌습니다. 이 행동을 무엇으로 설명할 수 있을까요? 두 파일은 모두 동일합니다.
추측하자면, /usr/share/dict/words
자주 사용하는 파일이라 이미 메모리에 버퍼링되어 있지 않을까요?
#define _GNU_SOURCE
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#define GET_TIME(now) \
do { \
struct timeval t; \
gettimeofday(&t, NULL); \
now = t.tv_sec + t.tv_usec / 1000000.0; \
} while (0)
#define REPORT(msg, time) \
do { \
printf("%-10s- %f\n", msg, time); \
} while (0)
#define SHOW_INVALID 0
struct dict {
int n;
char *data[110000];
};
int valid_word(char *input)
{
for (int i = 0; input[i]; i++) {
if (!islower(input[i]) && !(input[i] == '\n')) {
return 0;
}
}
return 1;
}
struct dict *get_dict(char *file)
{
struct dict *dict = calloc(1, sizeof(struct dict));
FILE *fp = fopen(file, "r");
char input[128];
while (fgets(input, 128, fp)) {
if (valid_word(input)) {
dict->data[dict->n++] = strdup(input);
} else {
#if SHOW_INVALID == 1
printf("Skipping invalid word %s", input);
#endif
}
}
fclose(fp);
return dict;
}
void destroy_dict(struct dict *dict)
{
for (int i = 0; i < dict->n; i++) {
free(dict->data[i]);
}
free(dict);
}
int search(struct dict *dict, int l, int r, char *word)
{
if (l > r) return -1;
int mid = l + (r - l) / 2;
if (!strcmp(dict->data[mid], word)) return mid;
if (strcmp(dict->data[mid], word) > 0) return search(dict, l, mid - 1, word);
return search(dict, mid + 1, r, word);
}
int match(struct dict *dict, char *word)
{
return search(dict, 0, dict->n - 1, word);
}
void test(struct dict *dict, char *file)
{
FILE *fp = fopen(file, "r");
char input[128];
while (fgets(input, 128, fp)) {
if (valid_word(input)) {
assert(match(dict, input) != -1);
} else {
assert(match(dict, input) == -1);
}
}
fclose(fp);
}
int main(void)
{
double init, start, end;
GET_TIME(init);
GET_TIME(start);
struct dict *dict = get_dict("words");
GET_TIME(end);
REPORT("setup", end - start);
GET_TIME(start);
test(dict, "words");
GET_TIME(end);
REPORT("words", end - start);
GET_TIME(start);
test(dict, "words_random");
GET_TIME(end);
REPORT("randwords", end - start);
GET_TIME(start);
destroy_dict(dict);
GET_TIME(end);
REPORT("teardown", end - start);
puts("");
REPORT("total", end - init);
return 0;
}
답변1
@Vilinkameni가 지적했듯이 GNU/Linux의 I/O 성능은 액세스되는 파일이 다른 물리적 장치 또는 파일 시스템 유형에 있는 경우 달라질 수 있습니다.
내 경우에는 WSL2가 가상 하드 디스크를 사용하지만 내 작업 디렉터리(WSL의 대상 디렉터리 cd
)는 실제로 내 C:/
드라이브에 있습니다. 따라서 /usr/share/dict/words
파일에 액세스할 때 여전히 WSL2 VHD에 있지만 파일을 내 C:/
드라이브에 복사하면 다른 "파일 시스템"에 있는 파일을 읽어야 하기 때문에 성능이 저하됩니다.
프로그램을 로 이동 하고 거기에 파일 복사본을 만들어 /usr/share/dict/
테스트했는데 words
이제 성능이 동일합니다.