siprikorea
siprikorea

Reputation: 63

The updating for "stat" function is slow?

Code Snippet:

void CMyLogger::Log(
    LogLevel level, LPCTSTR file, INT line, LPCTSTR func, LPCTSTR format, ...)
{
    time_t tCurrentLogTime;
    time(&tCurrentLogTime);

    tm tmCurrentLogTime;
    localtime_s(&tmCurrentLogTime, &tCurrentLogTime);

    // Check the date is changed
    if (m_tmCurrentLogTime.tm_year == tmCurrentLogTime.tm_year
        && m_tmCurrentLogTime.tm_mon == tmCurrentLogTime.tm_mon
        && m_tmCurrentLogTime.tm_mday == tmCurrentLogTime.tm_mday)
    {
        // Check the log file size has exceeded the maximum size
        struct _stat st;
        _tstat(m_szCurrentLogFile, &st);
        if (st.st_size > m_nMaxLogSize)
        {
            m_nCurrentLogIndex++;

            GetCurrentLogFile();

            CLogger::ClearOutputStreams();

            // Add logger
            AddOutputStream(new std::tofstream(m_szCurrentLogFile), true, LogLevel::Info);
        }
    }

    // The date is changed
    else
    {
        // Get current log time
        memcpy(&m_tmCurrentLogTime, &tmCurrentLogTime, sizeof(tmCurrentLogTime));

        m_nCurrentLogIndex = 0;

        DeleteOldFiles();
        GetCurrentLogFile();

        CLogger::ClearOutputStreams();

        // Add logger
        AddOutputStream(new std::tofstream(m_szCurrentLogFile), true, LogLevel::Info);
    }


    // Log
    va_list args;
    va_start(args, format);
    int length = _vsctprintf(format, args ) + 1;
    TCHAR* text =  new TCHAR[length];
    _vstprintf_s(text, length, format, args);
    va_end(args);

    CLogger::Log(level, file, line, func, text);

    delete [] text;
}

The above is a code snippet of log program. If the log file exceeds to 1 MB, create new log file. (xxx_000.log => xxx_001.log ...) I write the following code to test whether new log file is created when the log file exceeds to 1 MB:

#ifdef UNICODE
#define LOG(level, format, ...) CEagleLogger::GetInstance()->Log(level, __FILEW__, __LINE__, __FUNCTIONW__, format, __VA_ARGS__);
#else
#define LOG(level, format, ...) CEagleLogger::GetInstance()->Log(level, __FILE__, __LINE__, __FUNCTION__, format, __VA_ARGS__);
#endif

// ...

while (1)
    LOG(LogLevel::Info, _T("================================================================================"));

But, the log files are not created every 1 MB. The log file size is checked to stat function before write log. When actual log file size is exceeded to 1 MB, the 'stat' function is not exceed to 1 MB. The updating for "stat" function is slow?

The log size is different.

Upvotes: 0

Views: 579

Answers (1)

MSalters
MSalters

Reputation: 180030

stat is a POSIX function. _tstat is a Windows function intended to help porting POSIX code to Windows (but the _t stuff hinders porting the other way). Don't expect the best performance from such wrappers.

In particular, stat is the equivalent of FindFirstFile on Windows, and the CRT code included with Visual Studio confirms this: the first system call in _stat is to FindFirstFileEx(FindExInfoStandard ... FindExSearchNameMatch). . It gives you a number of properties of a directory entry, including the file size in the directory. For a file that's being written, that information is out of date. GetFileSize has the correct size

(Note that _stat is also doing quite a bit of work to get all kinds of properties that you don't even want. That was pretty cheap on UNIX, but on Windows the file access rights stuff has to be emulated. Not fast either.)

Upvotes: 1

Related Questions