commandCache.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "commandCache.h"
00019
00020 #include "command.h"
00021 #include "node.h"
00022 #include "packets.h"
00023
00024 using namespace std;
00025
00026 #define COMPACT
00027
00028
00029
00030
00031 namespace eq
00032 {
00033 namespace net
00034 {
00035 CommandCache::CommandCache()
00036 {
00037 for( size_t i = 0; i < CACHE_ALL; ++i )
00038 {
00039 _caches[ i ].push_back( new Command );
00040 _positions[ i ] = 0;
00041 }
00042 }
00043
00044 CommandCache::~CommandCache()
00045 {
00046 flush();
00047
00048 for( size_t i = 0; i < CACHE_ALL; ++i )
00049 {
00050 EQASSERT( _caches[i].size() == 1 );
00051 delete _caches[i].front();
00052 _caches[i].clear();
00053 }
00054 }
00055
00056 void CommandCache::flush()
00057 {
00058 for( size_t i = 0; i < CACHE_ALL; ++i )
00059 {
00060 CommandVector& cache = _caches[ i ];
00061 for( CommandVector::const_iterator j = cache.begin();
00062 j != cache.end(); ++j )
00063 {
00064 delete *j;
00065 }
00066 cache.clear();
00067 _positions[ i ] = 0;
00068 cache.push_back( new Command );
00069 }
00070 }
00071
00072 #ifdef PROFILE
00073 namespace
00074 {
00075 static base::a_int32_t _hits;
00076 static base::a_int32_t _misses;
00077 static base::a_int32_t _lookups;
00078 }
00079 #endif
00080
00081 Command& CommandCache::alloc( NodePtr node, NodePtr localNode,
00082 const uint64_t size )
00083 {
00084 CHECK_THREAD( _thread );
00085
00086 const Cache which = (size > Packet::minSize) ? CACHE_BIG : CACHE_SMALL;
00087 CommandVector& cache = _caches[ which ];
00088 size_t& i = _positions[ which ];
00089
00090 EQASSERT( !cache.empty( ));
00091
00092 #ifdef COMPACT
00093 const unsigned highWater = (which == CACHE_BIG) ? 10 : 1000;
00094 if( cache.size() > highWater && (i%10) == 0 )
00095 {
00096 int64_t keepFree( 30 * 1024 * 1024 );
00097 keepFree = EQ_MAX( keepFree, 10 );
00098 # ifdef PROFILE
00099 size_t freed( 0 );
00100 # endif
00101
00102 for( i = 0; i < cache.size(); ++i )
00103 {
00104 const Command* cmd = cache[i];
00105 if( !cmd->isFree( ))
00106 continue;
00107
00108 if( keepFree > 0 )
00109 {
00110 keepFree -= cmd->getAllocationSize();
00111 continue;
00112 }
00113
00114 cache.erase( cache.begin() + i );
00115 delete cmd;
00116 # ifdef PROFILE
00117 ++freed;
00118 # endif
00119 }
00120 # ifdef PROFILE
00121 EQINFO << "Freed " << freed << " packets, remaining " << cache.size()
00122 << std::endl;
00123 # endif
00124 }
00125 #endif
00126
00127 const size_t cacheSize = cache.size();
00128 i = i % cacheSize;
00129
00130 const size_t end = i + cacheSize;
00131
00132 for( ++i; i <= end; ++i )
00133 {
00134 #ifdef PROFILE
00135 ++_lookups;
00136 #endif
00137
00138 Command* command = cache[ i%cacheSize ];
00139 if( command->isFree( ))
00140 {
00141 #ifdef PROFILE
00142 const long hits = ++_hits;
00143 if( (hits%1000) == 0 )
00144 {
00145 size_t mem( 0 );
00146 size_t free( 0 );
00147 size_t packets( 0 );
00148
00149 for( size_t j = 0; j < CACHE_ALL; ++j )
00150 {
00151 CommandVector& cache1 = _caches[ j ];
00152 packets += cache1.size();
00153
00154 for( CommandVector::const_iterator k = cache1.begin();
00155 k != cache1.end(); ++k )
00156 {
00157 const Command* cmd = *k;
00158 mem += cmd->_packetAllocSize;
00159 if( cmd->isFree( ))
00160 ++free;
00161 }
00162 }
00163
00164 EQINFO << _hits << " hits, " << _misses << " misses, "
00165 << _lookups << " lookups, " << mem << "b allocated in "
00166 << packets << " packets (" << free << " free)"
00167 << std::endl;
00168 }
00169 #endif
00170 command->alloc( node, localNode, size );
00171 return *command;
00172 }
00173 }
00174
00175 #ifdef PROFILE
00176 ++_misses;
00177 #endif
00178
00179 const size_t add = (cacheSize >> 3) + 1;
00180 for( size_t j = 0; j < add; ++j )
00181 cache.push_back( new Command );
00182
00183 Command* command = cache.back();
00184 command->alloc( node, localNode, size );
00185 return *command;
00186 }
00187
00188 }
00189 }