现在的位置: 首页 > 综合 > 正文

调各种函数写文件的效率比较

2013年08月14日 ⁄ 综合 ⁄ 共 6143字 ⁄ 字号 评论关闭

测试代码:

#ifdef _MSC_VER
    #include <sys/stat.h>
    #include <io.h>
    #include <Windows.h>
#else
    #include <unistd.h>
#endif

#include <fcntl.h>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <fstream>

#ifdef _MSC_VER
    #define OPEN(fd, file) \
        fd = _open(file, O_CREAT | O_RDWR | O_APPEND, S_IWRITE | S_IREAD)

    #define WRITE(fd, data, len) \
        _write(fd, pszData, iDataLen)

    #define FLUSH(fd) \
        _commit(fd)

    #define CLOSE(fd) \
        _close(fd)

    #define SLEEP(s) \
        Sleep(1000 * s)
#else
    #define OPEN(fd, file) \
        umask(002);    \
        fd = open(file, O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP)

    #define WRITE(fd, data, len) \
        write(fd, pszData, iDataLen);

    #define FLUSH(fd) \
        fsync(fd)

    #define CLOSE(fd) \
        close(fd)

    #define SLEEP(s) \
        sleep(s)
#endif

static int s_iFd = -1;
static FILE * s_pFile = NULL;
static std::ofstream s_ofs;

enum TEST_TYPE
{
    TYPE_MIN, 
    TYPE_HANDLE = TYPE_MIN, 
    TYPE_FILE, 
    TYPE_OFSTREAM, 
    TYPE_MAX
};

const char * GetType(enum TEST_TYPE enType)
{
    switch (enType)
    {
        case TYPE_HANDLE:
        {
            return("handle");
        }
        case TYPE_FILE:
        {
            return("FILE");
        }
        case TYPE_OFSTREAM:
        {
            return("ofstream");
        }
        default:
        {
            return("unknown");
        }
    }
};

void OpenFile(enum TEST_TYPE enType)
{
    switch (enType)
    {
        case TYPE_HANDLE:
        {
            OPEN(s_iFd, "a.txt");
            if (s_iFd < 0)
            {
                fprintf(stderr, "open failed\n");
                exit(1);
            }
            break;
        }
        case TYPE_FILE:
        {
            s_pFile = fopen("b.txt", "w+");
            if (NULL == s_pFile)
            {
                fprintf(stderr, "fopen failed\n");
                exit(2);
            }
            break;
        }
        case TYPE_OFSTREAM:
        {
            s_ofs.open("c.txt", std::ios::binary | std::ios::app);
            if (!s_ofs)
            {
                fprintf(stderr, "ofstream::open failed\n");
                exit(3);
            }
            break;
        }
        default:
        {
            fprintf(stderr, "open: unknown type\n");
            exit(4);
            break;
        }
    }
}

void WriteFile(enum TEST_TYPE enType, const char * pszData, int iDataLen)
{
    if (NULL == pszData || 0 >= iDataLen)
    {
        return;
    }

    switch (enType)
    {
        case TYPE_HANDLE:
        {
            while (0 < iDataLen)
            {
                int iWirteLen = WRITE(s_iFd, pszData, iDataLen);
                if (0 > iWirteLen)
                {
                    fprintf(stderr, "write failed\n");
                    break;
                }
                pszData  += iWirteLen;
                iDataLen -= iWirteLen;
            }
            FLUSH(s_iFd);
            break;
        }
        case TYPE_FILE:
        {
            while (0 < iDataLen)
            {
                int iWirteLen = fwrite(pszData, 1, iDataLen, s_pFile);
                if (0 > iWirteLen)
                {
                    fprintf(stderr, "fwrite failed\n");
                    break;
                }
                pszData  += iWirteLen;
                iDataLen -= iWirteLen;
            }
            fflush(s_pFile);
            break;
        }
        case TYPE_OFSTREAM:
        {
            s_ofs.write(pszData, iDataLen);
            if (s_ofs.fail())
            {
                fprintf(stderr, "ofstream::write failed\n");
                s_ofs.clear();
            }
            s_ofs.flush();
            break;
        }
        default:
        {
            fprintf(stderr, "write: unknown type\n");
            exit(5);
            break;
        }
    }
}

void CloseFile(enum TEST_TYPE enType)
{
    switch (enType)
    {
        case TYPE_HANDLE:
        {
            CLOSE(s_iFd);
            break;
        }
        case TYPE_FILE:
        {
            fclose(s_pFile);
            break;
        }
        case TYPE_OFSTREAM:
        {
            s_ofs.close();
            break;
        }
        default:
        {
            fprintf(stderr, "close: unknown type\n");
            exit(6);
            break;
        }
    }
}

int main(int argc, char * argv[])
{
    const char szData[] = "1234567890123456789012345678901234567890123456789012345678901234567890";
    const int iDataLen = sizeof(szData) - 1;

    enum TEST_TYPE enIndex = TYPE_MIN;
    while (TYPE_MAX > enIndex)
    {
        const char * pszType = GetType(enIndex);

        OpenFile(enIndex);

        int iWriteCount = 0;
        int iPrintCount = 0;
        time_t tStartTime = time(NULL);
        time_t tLastTime = tStartTime;

        while (10 > iPrintCount)
        {
            WriteFile(enIndex, szData, iDataLen);
            ++iWriteCount;

            if (time(NULL) > tLastTime)
            {
                ++iPrintCount;
                tLastTime = time(NULL);
                fprintf(stdout, "type: %9s, speed: %9d\n", pszType, 
                    (iWriteCount / (tLastTime - tStartTime)));
            }
        }

        CloseFile(enIndex);

        enIndex = static_cast<enum TEST_TYPE>(enIndex + 1);

        SLEEP(2);
    };

    return(0);
}

测试结果:

Linux + no_flush: handle慢一个数量级, FILE与ofstream同一数量级, 但FILE略快
type:    handle, speed:    365147
type:    handle, speed:    553700
type:    handle, speed:    620208
type:    handle, speed:    660457
type:    handle, speed:    683569
type:    handle, speed:    698560
type:    handle, speed:    710284
type:    handle, speed:    718802
type:    handle, speed:    726606
type:    handle, speed:    729462
type:      FILE, speed:   4557587
type:      FILE, speed:   4805500
type:      FILE, speed:   4266081
type:      FILE, speed:   4493705
type:      FILE, speed:   4859939
type:      FILE, speed:   5003800
type:      FILE, speed:   5072787
type:      FILE, speed:   5132573
type:      FILE, speed:   4857114
type:      FILE, speed:   4878231
type:  ofstream, speed:   3706144
type:  ofstream, speed:   4089290
type:  ofstream, speed:   4019945
type:  ofstream, speed:   3723549
type:  ofstream, speed:   3517367
type:  ofstream, speed:   3674459
type:  ofstream, speed:   3925795
type:  ofstream, speed:   4079569
type:  ofstream, speed:   3827552
type:  ofstream, speed:   3762736

Linux + flush: handle慢四个数量级, FILE与ofstream同一数量级, 但FILE略快
type:    handle, speed:        19
type:    handle, speed:        29
type:    handle, speed:        37
type:    handle, speed:        37
type:    handle, speed:        36
type:    handle, speed:        36
type:    handle, speed:        36
type:    handle, speed:        37
type:    handle, speed:        36
type:    handle, speed:        38
type:      FILE, speed:    627707
type:      FILE, speed:    660472
type:      FILE, speed:    670974
type:      FILE, speed:    678343
type:      FILE, speed:    683366
type:      FILE, speed:    687264
type:      FILE, speed:    690667
type:      FILE, speed:    691783
type:      FILE, speed:    692458
type:      FILE, speed:    693900
type:  ofstream, speed:    623825
type:  ofstream, speed:    641605
type:  ofstream, speed:    657575
type:  ofstream, speed:    653685
type:  ofstream, speed:    663389
type:  ofstream, speed:    667315
type:  ofstream, speed:    668244
type:  ofstream, speed:    623023
type:  ofstream, speed:    624355
type:  ofstream, speed:    630020

Windows + no_flush: 三种方式, 速度都在同一个数量级, handle慢一些, 另外两个各有快慢;
type:    handle, speed:     71736
type:    handle, speed:     91307
type:    handle, speed:     99067
type:    handle, speed:    102946
type:    handle, speed:    105018
type:    handle, speed:    106260
type:    handle, speed:    107252
type:    handle, speed:    108264
type:    handle, speed:    108958
type:    handle, speed:    109396
type:      FILE, speed:    500532
type:      FILE, speed:    334409
type:      FILE, speed:    246716
type:      FILE, speed:    228381
type:      FILE, speed:    219697
type:      FILE, speed:    213099
type:      FILE, speed:    212147
type:      FILE, speed:    209722
type:      FILE, speed:    205950
type:      FILE, speed:    205227
type:  ofstream, speed:    435828
type:  ofstream, speed:    313958
type:  ofstream, speed:    297525
type:  ofstream, speed:    274231
type:  ofstream, speed:    296749
type:  ofstream, speed:    312720
type:  ofstream, speed:    330095
type:  ofstream, speed:    332609
type:  ofstream, speed:    322173
type:  ofstream, speed:    345480

Windows + flush: handle慢四个数量级, FILE比ofstream快一半
type:    handle, speed:        22
type:    handle, speed:        37
type:    handle, speed:        42
type:    handle, speed:        44
type:    handle, speed:        44
type:    handle, speed:        42
type:    handle, speed:        41
type:    handle, speed:        41
type:    handle, speed:        40
type:    handle, speed:        40
type:      FILE, speed:    121989
type:      FILE, speed:    125874
type:      FILE, speed:    126775
type:      FILE, speed:    127286
type:      FILE, speed:    127311
type:      FILE, speed:    127464
type:      FILE, speed:    127694
type:      FILE, speed:    127870
type:      FILE, speed:    128062
type:      FILE, speed:    127990
type:  ofstream, speed:     81132
type:  ofstream, speed:     80382
type:  ofstream, speed:     80439
type:  ofstream, speed:     80652
type:  ofstream, speed:     80746
type:  ofstream, speed:     80823
type:  ofstream, speed:     80845
type:  ofstream, speed:     80889
type:  ofstream, speed:     80810
type:  ofstream, speed:     80738

自己总结下: FILE比ofstream略快, 比handle快很多, 但是handle是无二次缓冲的IO, 文件刷入更及时

摘自我发的帖子:
write+commit与ofstream的比较

抱歉!评论已关闭.