与cstdio和std :: fstream相比,为什么SDL_RWops在写入文件时表现如此糟糕?

时间:2016-06-12 14:18:55

标签: c++ c file sdl sdl-2

我目前正在将我的爱好项目从std::fstream迁移到SDL_RWops(因为SDL_RWops是我在Android上加载资源的唯一简单选择。)

从文件中读取效果很好,但写入文件的速度非常慢。

考虑使用以下测试用例:

C标准IO - 0.217193秒

std::FILE *io = std::fopen("o.txt", "w");
for (int i = 0; i < 1024*1024*4; i++)
    std::putc('0', io);
std::fclose(io);

C ++流 - 0.278278秒

std::ofstream io("o.txt");
for (int i = 0; i < 1024*1024*4; i++)
    io << '0';
io.close();

SDL_RWops: - 17.9893秒

SDL_RWops *io = SDL_RWFromFile("o.txt", "w");
for (int i = 0; i < 1024*1024*4; i++)
    io->write(io, "0", 1, 1);
io->close(io);

所有测试用g ++ 5.3.0(mingw-w64)x86和-O3编译。我使用过SDL 2.0.4。

我也试过-O0,结果相似(慢0.02到0.25秒)。

在查看这些结果后,我有一个明显的问题:
为什么SDL_RWops写作性能如此差? 我该怎么做才能让它表现更好?

修改:以下是windows_file_write()的代码(来自SDL),这是io->write应指向的内容。 应该做缓冲输出,但我不确定它是如何工作的。

static size_t SDLCALL
windows_file_write(SDL_RWops * context, const void *ptr, size_t size, size_t num)
{
    size_t total_bytes;
    DWORD byte_written;
    size_t nwritten;

    total_bytes = size * num;

    if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE || total_bytes <= 0 || !size)
        return 0;

    if (context->hidden.windowsio.buffer.left) {
        SetFilePointer(context->hidden.windowsio.h,
                       -(LONG)context->hidden.windowsio.buffer.left, NULL,
                       FILE_CURRENT);
        context->hidden.windowsio.buffer.left = 0;
    }

    /* if in append mode, we must go to the EOF before write */
    if (context->hidden.windowsio.append) {
        if (SetFilePointer(context->hidden.windowsio.h, 0L, NULL, FILE_END) ==
            INVALID_SET_FILE_POINTER) {
            SDL_Error(SDL_EFWRITE);
            return 0;
        }
    }

    if (!WriteFile
        (context->hidden.windowsio.h, ptr, (DWORD)total_bytes, &byte_written, NULL)) {
        SDL_Error(SDL_EFWRITE);
        return 0;
    }

    nwritten = byte_written / size;
    return nwritten;
}

1 个答案:

答案 0 :(得分:0)

简而言之:我设法改进了它。现在我的 0.316382秒 ,这比其他解决方案慢一点。
但这是我生命中最糟糕的黑客之一。我很欣赏任何更好的解决方案。

如何完成:我已为SDL_RWFromFile()滚动自定义替换:我已从SDL_rwops.c复制粘贴实施并删除了所有预处理器分支,就好像仅{{1}已定义。该函数包含对HAVE_STDIO_H的调用,因此我也复制了粘贴SDL_RWFromFP()并对其应用了相同的修改。反过来,SDL_RWFromFP()依赖于SDL_RWFromFP()stdio_size()stdio_read()stdio_write()stdio_seek()(这些是stdio_close()的一部分因此,我也复制粘贴了它们。反过来,这些依赖于(再次!)某些领域的隐藏&#34; SDL_rwops.c内部的联合,在使用预处理器的窗口上禁用。我没有更改标题,而是更改了复制粘贴的代码,以使用&#34;隐藏&#34;的不同的成员。联合,存在于Windows上。 (这是安全的,因为除了我自己的和复制粘贴的代码之外什么也没有触及结构。)还做了一些其他调整,使代码可以用作C ++而不是C语言。

这就是我得到的:

struct SDL_RWops