`/usr/share/dict/words`コピーを読むのはファイル自体より10倍遅くなります。

`/usr/share/dict/words`コピーを読むのはファイル自体より10倍遅くなります。

私は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パフォーマンスは同じです。

関連情報