/*
 * fbench — бенчмарк буферизации FILE* (вариант B+) с опорными замерами.
 *
 *   0a. read() блоками по 512   — «пол»: чистая скорость диск+syscall,
 *       ровно те же вызовы, что делает буферный слой изнутри;
 *   0b. read() по 1 байту (16 КБ) — имитация НЕбуферизованного fgetc,
 *       ×6.25 даёт оценку на весь файл;
 *   1.  fgetc по всему файлу (102400 байт);
 *   2.  fgets построчно;
 *   3.  fputc 32 КБ (буфер: ~64 write-syscall'а вместо 32768).
 *
 * Интерпретация: если (1) ≈ (0a) — буферизация упирается в диск и
 * работает идеально; выигрыш против небуферизованного = (0b)×6.25 − (1).
 * Время — time(), секундная гранулярность.  На дискете доминирует FDD;
 * для чистого замера скопировать fbench.exe + big.txt на HDD (C:).
 */

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>

static char blk[512];
static char line[128];

int main(void)
{
    long   n;
    int    c, fd, r;
    time_t t0, t1;

    /* ----- 0a. Пол: блочный read по 512 ----- */
    fd = open("BIG.TXT", O_RDONLY);
    if (fd < 0) { puts("BIG.TXT not found"); return 1; }
    t0 = time(NULL);
    n = 0;
    while ((r = read(fd, blk, 512)) > 0) n += r;
    t1 = time(NULL);
    printf("read512: %ld bytes, %ld s  (floor)\n", n, (long)(t1 - t0));
    close(fd);

    /* ----- 0b. Имитация небуферизованного fgetc: read по 1 байту ----- */
    fd = open("BIG.TXT", O_RDONLY);
    t0 = time(NULL);
    for (n = 0; n < 16384L; n++) {
        if (read(fd, blk, 1) != 1) break;
    }
    t1 = time(NULL);
    printf("read1  : %ld bytes, %ld s  (x6.25 = unbuffered est.)\n",
           n, (long)(t1 - t0));
    close(fd);

    /* ----- 1. fgetc по всему файлу ----- */
    FILE *fp = fopen("BIG.TXT", "r");
    if (!fp) { puts("fopen failed"); return 1; }
    t0 = time(NULL);
    n  = 0;
    while ((c = fgetc(fp)) != EOF) n++;
    t1 = time(NULL);
    printf("fgetc  : %ld bytes, %ld s\n", n, (long)(t1 - t0));

    /* ----- 2. fgets построчно ----- */
    rewind(fp);
    t0 = time(NULL);
    n  = 0;
    while (fgets(line, sizeof(line), fp)) n++;
    t1 = time(NULL);
    printf("fgets  : %ld lines, %ld s\n", n, (long)(t1 - t0));
    fclose(fp);

    /* ----- 3. fputc 32 КБ ----- */
    fp = fopen("FBENCH.TMP", "w");
    if (!fp) { puts("cannot create FBENCH.TMP"); return 1; }
    t0 = time(NULL);
    for (n = 0; n < 32768L; n++) {
        if (fputc('x', fp) == EOF) { puts("fputc error"); return 1; }
    }
    if (fclose(fp)) { puts("fclose error"); return 1; }
    t1 = time(NULL);
    printf("fputc  : 32768 bytes, %ld s\n", (long)(t1 - t0));
    unlink("FBENCH.TMP");

    puts("fbench done.");
    return 0;
}
