オンライン実行

言語
コンパイルコマンド
言語を選ぶと既定コマンドが自動入力されます。自由に編集でき、空欄なら既定を使用します。_filename_ はソースファイル名に置換されます。
実行コマンド
ソースコード
タブ幅 
/*
 * fcat: argv[1] のファイルをそのまま stdout へ流す「最小・最速」バイナリ。
 *
 * 用途: Text 言語(テキスト直接提出)の実行コマンド。従来は /usr/bin/cat を使って
 * いたが、動的リンク(ld.so)+glibc CRT 初期化(__libc_start_main)の起動コストが
 * 実行時間に丸ごと乗っていた(cpuset 1コア固定で実測 ~550us)。
 *
 * fcat は libc/CRT を一切使わない(_start を naked asm で自前定義し、open/sendfile/
 * read/write/exit を生 syscall で叩く)ため、ld.so も glibc 初期化も無く、静的リンク
 * でも ~9KB。同条件で実測 ~230us(cat の約 2.4 倍速)。出力は cat とバイト完全一致。
 *
 * ビルド
 *   gcc -Os -static -nostdlib -ffreestanding -fno-stack-protector fcat.c -o /usr/bin/fcat
 *
 * 注: _start を C 関数にすると、コンパイラのプロローグ挿入で %rsp が動き、そこから
 * 読む argc/argv がずれる(実測でハマった)。エントリは必ず naked asm にし、最初の命令で
 * argc/argv を確定させてから通常の C 関数 run() へ渡す。
 *
 * x86-64 Linux 専用。
 */
__asm__(
    ".text\n"
    ".global _start\n"
    "_start:\n"
    "  xor %rbp,%rbp\n"      /* frame pointer をクリア */
    "  mov (%rsp),%rdi\n"    /* argc = [rsp] */
    "  lea 8(%rsp),%rsi\n"   /* argv = rsp+8 */
    "  call run\n"
    "  mov %rax,%rdi\n"      /* exit code = run() の戻り値 */
    "  mov $60,%rax\n"       /* SYS_exit */
    "  syscall\n"
);

/* 3引数 syscall。x86-64: nr=rax, arg=rdi,rsi,rdx。*/
static long sc(long n, long a, long b, long c) {
    long r;
    __asm__ volatile("syscall" : "=a"(r) : "a"(n), "D"(a), "S"(b), "d"(c)
                     : "rcx", "r11", "memory");
    return r;
}

/* 4引数 syscall(第4引数は r10)。sendfile 用。*/
static long sc4(long n, long a, long b, long c, long d) {
    long r;
    register long r10 __asm__("r10") = d;
    __asm__ volatile("syscall" : "=a"(r) : "a"(n), "D"(a), "S"(b), "d"(c), "r"(r10)
                     : "rcx", "r11", "memory");
    return r;
}

#define SYS_read 0
#define SYS_write 1
#define SYS_open 2
#define SYS_sendfile 40

static char buf[1 << 16];

long run(long argc, char **argv) {
    if (argc < 2) return 1;
    long fd = sc(SYS_open, (long)argv[1], 0 /*O_RDONLY*/, 0);
    if (fd < 0) return 1;

    /* まず sendfile(ゼロコピー)。offset NULL は fd 位置を進める。0=EOF で完了。
       非対応/失敗(パイプ宛て等)なら負値で抜けて read/write にフォールバック。*/
    for (;;) {
        long n = sc4(SYS_sendfile, 1, fd, 0, 1 << 20);
        if (n == 0) return 0;
        if (n < 0) break;
    }
    /* フォールバック: sendfile が進めた位置の続きから read/write でコピーする。*/
    for (;;) {
        long r = sc(SYS_read, fd, (long)buf, sizeof buf);
        if (r < 0) return 1;
        if (r == 0) return 0;
        long w = 0;
        while (w < r) {
            long k = sc(SYS_write, 1, (long)(buf + w), r - w);
            if (k <= 0) return 1;
            w += k;
        }
    }
}
標準入力
ログインしている場合のみ実行できます。
結果を非表示にする
一般公開

実行結果

コンパイルメッセージ
標準出力
標準エラー出力
実行時間 : 0 ms + 99µs
コンパイル時間/使用メモリ : 756 ms
24,388 KB
実行使用メモリ : 9316 KB
終了ステータス : 1
コード長 : 3137 Byte