Changeset 365 for trunk/src/core


Ignore:
Timestamp:
05/16/15 17:40:16 (10 years ago)
Author:
epyon
Message:
  • overhaul of logging: no longer stream operated no longer using STL no memory allocation shorthand macros fast file and console I/O
Location:
trunk
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk

    • Property svn:global-ignores set to
      vs2012
      vs2013
      gmake
      gmake-clang
  • trunk/src/core/io_event.cc

    r338 r365  
    4646void nv::log_event( const io_event& e )
    4747{
    48         NV_LOG( LOG_INFO, "Event: " << get_io_event_name( e.type ) );
     48        NV_LOG_INFO( "Event: ", get_io_event_name( e.type ) );
    4949}
    5050
  • trunk/src/core/library.cc

    r319 r365  
    7171        return true;
    7272    }
    73     NV_LOG( LOG_NOTICE, "library : loading '" + m_name + "'..." );
     73    NV_LOG_NOTICE( "library : loading '", m_name, "'..." );
    7474
    7575    string name = m_name;
     
    8686    if ( m_handle == NULL )
    8787    {
    88                 NV_LOG( LOG_NOTICE, "library : '" + name + "' failed to open." );
     88                NV_LOG_NOTICE( "library : '", name, "' failed to open." );
    8989                return false;
    9090    }
    91     NV_LOG( LOG_NOTICE, "library : '" + name + "' loaded." );
     91    NV_LOG_NOTICE( "library : '", name, "' loaded." );
    9292        return true;
    9393}
     
    117117    if ( NV_LIB_CLOSE( (NV_LIB_HANDLE)m_handle ) )
    118118    {
    119         NV_LOG( LOG_ERROR, "library : can't close library '" + m_name + "'!" );
     119        NV_LOG_ERROR( "library : can't close library '", m_name, "'!" );
    120120    }
    121121    m_handle = NULL;
  • trunk/src/core/logger.cc

    r319 r365  
    66
    77#include "nv/core/common.hh"
    8 #include <iostream>
    9 #include <utility>
    10 #include <algorithm>
    11 #include <fstream>
    12 #include <ctime>
     8#include "nv/core/time.hh"
    139#include <cstdio>
    14 #include "nv/core/exception.hh"
    1510#if NV_PLATFORM == NV_WINDOWS
    1611#define WIN32_LEAN_AND_MEAN
     
    8984
    9085// log function
    91 void logger::log( log_level level, const std::string& message )
    92 {
    93         // get the iterator to the beginning of the log_sink list
    94         log_sink_list::reverse_iterator it = m_log_sinks.rbegin();
    95 
    96         // iterate
    97         while ( it != m_log_sinks.rend() )
    98         {
    99                 // if we have a log sink with high enough level...
    100                 if ( it->first >= level )
     86void logger::log( log_level level, const string_ref& message )
     87{
     88        for ( auto& sink_info : m_log_sinks )
     89        {
     90                if ( sink_info.sink && (sink_info.level >= (uint32)level) )
    10191                {
    10292                        // log and iterate
    103                         it->second->log( level, message );
     93                        sink_info.sink->log( level, message );
    10494                }
    105                 else
     95        }
     96}
     97
     98// add a new sink
     99void logger::add_sink( log_sink* sink, int level )
     100{
     101        // add a sink
     102        for ( auto& sink_info : m_log_sinks )
     103        {
     104                if ( sink_info.sink == nullptr )
    106105                {
    107                         // otherwise return, the list is sorted by log level
     106                        sink_info.sink  = sink;
     107                        sink_info.level = (uint32)level;
    108108                        return;
    109109                }
    110                 ++it;
    111         }
    112 }
    113 
    114 // add a new sink
    115 void logger::add_sink( log_sink* sink, int level )
    116 {
    117         // add a sink
    118         m_log_sinks.push_back( std::make_pair( log_level(level), sink ) );
    119         // and sort the list (default sort of pairs is by first element)
    120         m_log_sinks.sort();
     110        }
     111        NV_ASSERT( false, "ran out of log sink space!" );
    121112}
    122113
     
    124115bool logger::remove_sink( log_sink* sink )
    125116{
    126         // get the iterator to the beginning of the log_sink list
    127         log_sink_list::iterator it = m_log_sinks.begin();
    128 
    129         // iterate
    130         while ( it != m_log_sinks.end() )
    131         {
    132                 // found?
    133                 if ( it->second == sink )
     117        for ( auto& sink_info : m_log_sinks )
     118        {
     119                if ( sink_info.sink == sink )
    134120                {
    135                         // erase and return true to report success
    136                         m_log_sinks.erase(it);
     121                        delete sink_info.sink;
     122                        sink_info.sink = nullptr;
    137123                        return true;
    138124                }
    139                 ++it;
    140         }
    141 
     125        }
    142126        // not found, return false
    143127        return false;
     
    147131logger::~logger()
    148132{
    149         // while we have sinks
    150         while ( !m_log_sinks.empty() )
    151         {
    152                 // delete the last one
    153                 delete m_log_sinks.back().second;
    154                 // and pop it
    155                 m_log_sinks.pop_back();
     133        // delete all sinks
     134        for ( auto& sink_info : m_log_sinks )
     135        {
     136                delete sink_info.sink;
    156137        }
    157138}
     
    159140
    160141// console logging
    161 void log_console_sink::log( log_level level, const std::string& message )
    162 {
    163         if (m_color)
    164         {
    165 #if NV_PLATFORM == NV_WINDOWS
    166                 SetConsoleTextAttribute( m_handle, FOREGROUND_INTENSITY );
    167                 std::cout << timestamp() << " [";
    168                 SetConsoleTextAttribute( m_handle, log_color[ (level) / 10 ] );
    169                 std::cout << NV_LOG_LEVEL_NAME_PAD(level);
    170                 SetConsoleTextAttribute( m_handle, FOREGROUND_INTENSITY );
    171                 std::cout << "] ";
    172                 SetConsoleTextAttribute( m_handle, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
    173                 std::cout << message << std::endl;
    174 #else
    175                 std::cout << "\33[30;1m" << timestamp() << " [" << log_color[ (level) / 10 ] << NV_LOG_LEVEL_NAME_PAD(level) << "\33[30;1m] \33[37;1m" << message << std::endl;
    176 #endif
    177         }
     142void log_console_sink::log( log_level level, const string_ref& message )
     143{
     144#if NV_PLATFORM == NV_WINDOWS
     145        if ( m_color ) SetConsoleTextAttribute( m_handle, FOREGROUND_INTENSITY );
     146        string_ref stamp( timestamp() );
     147        WriteConsole( m_handle, stamp.data(), stamp.size(), nullptr, nullptr );
     148        WriteConsole( m_handle, " [", 2, nullptr, nullptr );
     149        if (m_color) SetConsoleTextAttribute( m_handle, log_color[( level ) / 10] );
     150        WriteConsole( m_handle, NV_LOG_LEVEL_NAME_PAD( level ), 8, nullptr, nullptr );
     151        if ( m_color ) SetConsoleTextAttribute( m_handle, FOREGROUND_INTENSITY );
     152        WriteConsole( m_handle, "] ", 2, nullptr, nullptr );
     153        if ( m_color ) SetConsoleTextAttribute( m_handle, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE );
     154        WriteConsole( m_handle, message.data(), message.size(), nullptr, nullptr );
     155        WriteConsole( m_handle, "\n", 1, nullptr, nullptr );
     156#else
     157        if ( m_color ) fwrite( "\33[30;1m", 7, 1, stdout );
     158        fwrite( stamp.data(), stamp.size(), 1, stdout );
     159        fwrite( " [", 2, 1, stdout );
     160        if ( m_color )
     161        {
     162                const char* lcolor = log_color[( level ) / 10];
     163                fwrite( lcolor, strlen(lcolor), 1, stdout );
     164        }
     165        fwrite( NV_LOG_LEVEL_NAME_PAD( level ), 8, 1, stdout );
     166        if ( m_color )
     167                fwrite( "\33[30;1m] \33[37;1m", 16, 1, stdout );
    178168        else
    179         {
    180         std::cout << timestamp() << " [" << NV_LOG_LEVEL_NAME_PAD(level) << "] " << message << std::endl;
    181         }
    182 }
    183 
    184 // stream logging
    185 void log_stream_sink::log( log_level level, const std::string& message )
    186 {
    187         // if flushing is enabled
    188         if ( m_flush )
    189         {
    190                 // write and flush using std::endl
    191                 *m_stream << timestamp() << " [" << NV_LOG_LEVEL_NAME(level) << "] " << message << std::endl;
    192         }
    193         else
    194         {
    195                 // write and end with "\n" (no flush)
    196                 *m_stream << timestamp() << " [" << NV_LOG_LEVEL_NAME(level) << "] " << message << "\n";
    197         }
    198 }
    199 
    200 // file logging
    201 log_file_sink::log_file_sink( const std::string file_name, bool flush_always /*= true */ )
    202         : log_stream_sink( nullptr, flush_always )
    203 {
    204         // create the stream manually
    205         std::ofstream* fstream = new std::ofstream( file_name );
    206 
    207         // check if it's open
    208         if ( !fstream->is_open() )
    209         {
    210                 // throw if not open
    211                 NV_THROW( runtime_error, "Could not open file \""+file_name+"\" for logging!" );
    212         }
    213 
    214         m_stream = fstream;
    215 }
    216 
    217 // file logger destructor
    218 log_file_sink::~log_file_sink()
    219 {
    220         // close the file
    221         dynamic_cast< std::ofstream* >(m_stream)->close();
    222         // dispose of the stream
    223         delete m_stream;
    224 }
     169                fwrite( "] ", 2, 1, stdout );
     170        fwrite( stamp.data(), stamp.size(), 1, stdout );
     171        fwrite( "\n", 1, 1, stdout );
     172#endif
     173}
     174
     175// handle logging
     176void log_handle_sink::log( log_level level, const string_ref& message )
     177{
     178        string_ref stamp( timestamp() );
     179#if 0 // NV_PLATFORM == NV_WINDOWS
     180        // Turns out WriteFile on Windows is unbuffered and quite slower than fwrite
     181        // due to this fact -- especially UNUSABLE with manual FlushFileBuffers
     182        // If we want to get rid of C runtime, this would need a buffered I/O layer.
     183        DWORD unused = 0;
     184        WriteFile( m_handle, stamp.data(), stamp.size(), &unused, nullptr );
     185        WriteFile( m_handle, " [", 2, &unused, nullptr );
     186        WriteFile( m_handle, NV_LOG_LEVEL_NAME_PAD( level ), 8, &unused, nullptr );
     187        WriteFile( m_handle, "] ", 2, &unused, nullptr );
     188        WriteFile( m_handle, message.data(), message.size(), &unused, nullptr );
     189        WriteFile( m_handle, "\n", 1, &unused, nullptr );
     190        //if ( m_flush ) FlushFileBuffers( m_handle );
     191#else
     192        fwrite( stamp.data(), stamp.size(), 1, (FILE*)m_handle );
     193        fwrite( " [", 2, 1, (FILE*)m_handle );
     194        fwrite( NV_LOG_LEVEL_NAME_PAD( level ), 8, 1, (FILE*)m_handle );
     195        fwrite( "] ", 2, 1, (FILE*)m_handle );
     196        fwrite( message.data(), message.size(), 1, (FILE*)m_handle );
     197        fwrite( "\n", 1, 1, (FILE*)m_handle );
     198        if ( m_flush ) fflush( (FILE*)m_handle );
     199#endif
     200}
     201
     202nv::log_file_sink::log_file_sink( const string_ref& file_name, bool flush_always /*= true */ )
     203        : log_handle_sink( nullptr, flush_always )
     204{
     205#if 0 // NV_PLATFORM == NV_WINDOWS
     206        // See comments in log_handle_sink
     207        HANDLE handle = CreateFile( file_name.data(), GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr );
     208        if ( INVALID_HANDLE_VALUE == handle )
     209        {
     210                NV_ASSERT( false, "invalid log handle" );
     211        }
     212        m_handle = handle;
     213#else
     214        m_handle = fopen( file_name.data(), "w" );
     215#endif
     216}
     217
     218nv::log_file_sink::~log_file_sink()
     219{
     220#if 0 // NV_PLATFORM == NV_WINDOWS
     221        // See comments in log_handle_sink
     222        CloseHandle( m_handle );
     223#else
     224        fclose( (FILE*) m_handle );
     225#endif
     226}
     227
    225228
    226229nv::log_console_sink::log_console_sink( bool coloring )
     
    234237}
    235238
    236 const char* nv::log_sink::timestamp() const
    237 {
    238         std::clock_t time = std::clock();
    239         unsigned int secs = (unsigned int)(time / CLOCKS_PER_SEC);
    240         unsigned int mm   = (unsigned int)(time*100 / CLOCKS_PER_SEC) % 100;
     239string_ref nv::log_sink::timestamp() const
     240{
     241        uint32 ms = get_system_ms();
     242        unsigned int secs = (unsigned int)(ms / 1000);
     243        unsigned int mm   = (unsigned int)( ms * 100 / 1000 ) % 100;
    241244        unsigned int h    = (unsigned int)(secs / (60*60));
    242245        unsigned int m    = (unsigned int)(secs / 60) % 60;
    243246        unsigned int s    = secs % 60;
    244         static char buffer[128];
    245 #if NV_PLATFORM == NV_WINDOWS
    246         sprintf_s( buffer, 128, "%02d:%02d:%02d.%02d", h, m, s, mm );
    247 #else
    248         sprintf( buffer, "%02d:%02d:%02d.%02d", h, m, s, mm );
     247        static char buffer[16];
     248#if NV_PLATFORM == NV_WINDOWS
     249        sprintf_s( buffer, 16, "%02d:%02d:%02d.%02d", h, m, s, mm );
     250#else
     251        snprintf( buffer, 16, "%02d:%02d:%02d.%02d", h, m, s, mm );
    249252#endif
    250253        buffer[11] = '\0';
    251         return buffer;
    252 }
    253 
    254 const char* nv::log_sink::level_name( log_level level ) const
     254        return string_ref( buffer, 10 );
     255}
     256
     257string_ref nv::log_sink::level_name( log_level level ) const
    255258{
    256259        return NV_LOG_LEVEL_NAME( level );
    257260}
    258261
    259 const char* nv::log_sink::padded_level_name( log_level level ) const
    260 {
    261         return NV_LOG_LEVEL_NAME_PAD( level );
    262 }
     262string_ref nv::log_sink::padded_level_name( log_level level ) const
     263{
     264        return string_ref( NV_LOG_LEVEL_NAME_PAD( level ), 8 );
     265}
     266
  • trunk/src/core/profiler.cc

    r319 r365  
    88#include <ios>
    99#include "nv/core/time.hh"
     10#include "nv/core/logging.hh"
    1011
    1112using namespace nv;
     
    9798}
    9899
    99 
    100100void profiler::log_report()
    101101{
    102102        m_root->stop();
    103         NV_LOG( LOG_INFO, "-- PROFILER REPORT -----------------------------------------" );
    104         NV_LOG( LOG_INFO, std::left << std::setw(24) << "TAG"
     103        NV_LOG_INFO( "-- PROFILER REPORT -----------------------------------------" );
     104        NV_LOG_STREAM( LOG_INFO, std::left << std::setw(24) << "TAG"
    105105                << std::setw(7) << "%PARNT"
    106106                << std::setw(7) << "CALLS"
     
    108108                << std::setw(10) << "AVG(ms)" );
    109109        log_node_children( "", m_root );
    110         NV_LOG( LOG_INFO, "-- PROFILER REPORT END -------------------------------------" );
     110        NV_LOG_INFO( "-- PROFILER REPORT END -------------------------------------" );
    111111        m_root->start();
    112112}
     
    119119                if ( c->m_calls > 0 )
    120120                {
    121                         NV_LOG( LOG_INFO, std::left << std::setw(24) << ind + c->m_tag
     121                        NV_LOG_STREAM( LOG_INFO, std::left << std::setw(24) << ind + c->m_tag
    122122                                << std::setw(7) << std::setprecision(2) << std::fixed << ( (double)c->m_total_time_us / (double)c->m_parent->m_total_time_us ) * 100.0
    123123                                << std::setw(7) << c->m_calls
Note: See TracChangeset for help on using the changeset viewer.