Back to index

texmacs  1.0.7.15
fast_alloc.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : Fast memory allocation
00004 * DESCRIPTION: Fast allocations is realized by using a linked list
00005 *              of allocations for each fixed size divisible by
00006 *              a word legth up to MAX_FAST. Otherwise,
00007 *              usual memory allocation is used.
00008 * ASSUMPTIONS: The word size of the computer is 4.
00009 *              Otherwise, change WORD_LENGTH.
00010 * COPYRIGHT  : (C) 1999  Joris van der Hoeven
00011 *******************************************************************************
00012 * This software falls under the GNU general public license version 3 or later.
00013 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00014 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00015 ******************************************************************************/
00016 
00017 #include "fast_alloc.hpp"
00018 
00019 char   alloc_table[MAX_FAST]; // Static declaration initializes with NULL's
00020 char*  alloc_mem=NULL;
00021 size_t alloc_remains=0;
00022 int    allocated=0;
00023 int    fast_chunks=0;
00024 int    large_uses=0;
00025 int    MEM_DEBUG=0;
00026 int    mem_used ();
00027 
00028 /*****************************************************************************/
00029 // General purpose fast allocation routines
00030 /*****************************************************************************/
00031 
00032 void*
00033 safe_malloc (register size_t sz) {
00034   void* ptr= malloc (sz);
00035   if (ptr==NULL) {
00036     cerr << "Fatal error: out of memory\n";
00037     abort ();
00038   }
00039   return ptr;
00040 }
00041 
00042 void*
00043 enlarge_malloc (register size_t sz) {
00044   if (alloc_remains<sz) {
00045     alloc_mem    = (char *) safe_malloc (BLOCK_SIZE);
00046     alloc_remains= BLOCK_SIZE;
00047     fast_chunks++;
00048   }
00049   register void* ptr= alloc_mem;
00050   alloc_mem    += sz;
00051   alloc_remains-= sz;
00052   return ptr;
00053 }
00054 
00055 void*
00056 fast_alloc (register size_t sz) {
00057   sz= (sz+WORD_LENGTH_INC)&WORD_MASK;
00058   if (sz<MAX_FAST) {
00059     register void *ptr= alloc_ptr (sz);
00060     if (ptr==NULL) return enlarge_malloc (sz);
00061     alloc_ptr (sz)= ind (ptr);
00062     return ptr;
00063   }
00064   else {
00065     if (MEM_DEBUG>=3) cout << "Big alloc of " << sz << " bytes\n";
00066     if (MEM_DEBUG>=3) cout << "Memory used: " << mem_used () << " bytes\n";
00067     large_uses += sz;
00068     return safe_malloc (sz);
00069   }
00070 }
00071 
00072 void
00073 fast_free (register void* ptr, register size_t sz) {
00074   sz=(sz+WORD_LENGTH_INC)&WORD_MASK;
00075   if (sz<MAX_FAST) {
00076     ind (ptr)     = alloc_ptr (sz);
00077     alloc_ptr (sz)= ptr;
00078   }
00079   else {
00080     if (MEM_DEBUG>=3) cout << "Big free of " << sz << " bytes\n";
00081     large_uses -= sz;    
00082     free (ptr);
00083     if (MEM_DEBUG>=3) cout << "Memory used: " << mem_used () << " bytes\n";
00084   }
00085 }
00086 
00087 /*
00088 void*
00089 fast_alloc (register size_t s) {
00090   register void* ptr;
00091   s= (s+ WORD_LENGTH+ WORD_LENGTH_INC)&WORD_MASK;
00092   if (s<MAX_FAST) {
00093     ptr= alloc_ptr(s);
00094     if (ptr==NULL) ptr= enlarge_malloc (s);
00095     else alloc_ptr(s)= ind(ptr);
00096   }
00097   else {
00098     if (MEM_DEBUG>=3) cout << "Big alloc of " << s << " bytes\n";
00099     if (MEM_DEBUG>=3) cout << "Memory used: " << mem_used () << " bytes\n";
00100     ptr= safe_malloc (s);
00101     large_uses += s;
00102   }
00103   *((size_t *) ptr)=s;
00104   return (void*) (((char*) ptr)+ WORD_LENGTH);
00105 }
00106 
00107 void
00108 fast_free (register void* ptr, register size_t sz) {
00109   ptr= (void*) (((char*) ptr)- WORD_LENGTH);
00110   register size_t s= *((size_t *) ptr);
00111   sz= (sz+ WORD_LENGTH+ WORD_LENGTH_INC)&WORD_MASK;
00112   if (s != sz) {
00113     cerr << "At " << ptr << ": " << sz << " -> " << s << "\n";
00114     assert (s == sz);
00115   }
00116   if (s<MAX_FAST) {
00117     ind(ptr)    = alloc_ptr(s);
00118     alloc_ptr(s)= ptr;
00119   }
00120   else {
00121     if (MEM_DEBUG>=3) cout << "Big free of " << s << " bytes\n";
00122     free (ptr);
00123     large_uses -= s;
00124     if (MEM_DEBUG>=3) cout << "Memory used: " << mem_used () << " bytes\n";
00125   }
00126 }
00127 */
00128 
00129 void*
00130 fast_new (register size_t s) {
00131   register void* ptr;
00132   s= (s+ WORD_LENGTH+ WORD_LENGTH_INC)&WORD_MASK;
00133   if (s<MAX_FAST) {
00134     ptr= alloc_ptr(s);
00135     if (ptr==NULL) ptr= enlarge_malloc (s);
00136     else alloc_ptr(s)= ind(ptr);
00137   }
00138   else {
00139     if (MEM_DEBUG>=3) cout << "Big alloc of " << s << " bytes\n";
00140     if (MEM_DEBUG>=3) cout << "Memory used: " << mem_used () << " bytes\n";
00141     ptr= safe_malloc (s);
00142     //if ((((int) ptr) & 15) != 0) cout << "Unaligned new " << ptr << "\n";
00143     large_uses += s;
00144   }
00145   *((size_t *) ptr)=s;
00146   return (void*) (((char*) ptr)+ WORD_LENGTH);
00147 }
00148 
00149 void
00150 fast_delete (register void* ptr) {
00151   ptr= (void*) (((char*) ptr)- WORD_LENGTH);
00152   register size_t s= *((size_t *) ptr);
00153   if (s<MAX_FAST) {
00154     ind(ptr)    = alloc_ptr(s);
00155     alloc_ptr(s)= ptr;
00156   }
00157   else {
00158     if (MEM_DEBUG>=3) cout << "Big free of " << s << " bytes\n";
00159     //if ((((int) ptr) & 15) != 0) cout << "Unaligned delete " << ptr << "\n";
00160     free (ptr);
00161     large_uses -= s;
00162     if (MEM_DEBUG>=3) cout << "Memory used: " << mem_used () << " bytes\n";
00163   }
00164 }
00165 
00166 /******************************************************************************
00167 * Fast allocation of blocks whose sizes are small multiples of WORD_LENGTH
00168 ******************************************************************************/
00169 
00170 void*
00171 fast_alloc_mw (register size_t s)
00172 {
00173   if (s<MAX_FAST) {
00174     register void *ptr= alloc_ptr(s);
00175     if (ptr==NULL) return enlarge_malloc (s);
00176     alloc_ptr(s)= ind(ptr);
00177     return ptr;
00178   }
00179   else return safe_malloc (s);
00180 }
00181 
00182 void
00183 fast_free_mw (register void* ptr, register size_t s)
00184 {
00185   if (s<MAX_FAST) {
00186     ind(ptr)    = alloc_ptr(s);
00187     alloc_ptr(s)= ptr;
00188   }
00189   else free (ptr);
00190 }
00191 
00192 /******************************************************************************
00193 * Statistics
00194 ******************************************************************************/
00195 
00196 int
00197 compute_free (void* ptr) {
00198   int i=-1;
00199   while (ptr!=NULL) {
00200     i++;
00201     ptr= ind (ptr);
00202   }
00203   return i;
00204 }
00205 
00206 int
00207 mem_used () {
00208   int free_bytes= alloc_remains;
00209   int chunks_use= BLOCK_SIZE*fast_chunks;
00210   int i;
00211   for (i=WORD_LENGTH; i<MAX_FAST; i+=WORD_LENGTH)
00212     free_bytes += i*compute_free (alloc_table+i);
00213   int small_uses= chunks_use- free_bytes;
00214   return small_uses+ large_uses;
00215 }
00216 
00217 void
00218 mem_info () {
00219   cout << "\n---------------- memory statistics ----------------\n";
00220   int free_bytes= alloc_remains;
00221   int chunks_use= BLOCK_SIZE*fast_chunks;
00222   int i;
00223   for (i=WORD_LENGTH; i<MAX_FAST; i+=WORD_LENGTH)
00224     free_bytes += i*compute_free (alloc_table+i);
00225   int small_uses= chunks_use- free_bytes;
00226   int total_uses= small_uses+ large_uses;
00227   // cout << "Fast chunks   : " << chunks_use << " bytes\n";
00228   // cout << "Free on chunks: " << alloc_remains << " bytes\n";
00229   cout << "User          : " << total_uses << " bytes\n";
00230   cout << "Allocator     : " << chunks_use+ large_uses << " bytes\n";
00231   cout << "Small mallocs : "
00232        << ((100*((float) small_uses))/((float) total_uses)) << "%\n";
00233 }
00234 
00235 /******************************************************************************
00236 * Redefine standard new and delete
00237 ******************************************************************************/
00238 
00239 #if defined(X11TEXMACS) && (!defined(NO_FAST_ALLOC))
00240 
00241 void*
00242 operator new (register size_t s) {
00243   register void* ptr;
00244   s= (s+ WORD_LENGTH+ WORD_LENGTH_INC)&WORD_MASK;
00245   if (s<MAX_FAST) {
00246     ptr= alloc_ptr(s);
00247     if (ptr==NULL) ptr= enlarge_malloc (s);
00248     else alloc_ptr(s)= ind(ptr);
00249   }
00250   else {
00251     ptr= safe_malloc (s);
00252     large_uses += s;
00253   }
00254   *((size_t *) ptr)=s;
00255   return (void*) (((char*) ptr)+ WORD_LENGTH);
00256 }
00257 
00258 void
00259 operator delete (register void* ptr) {
00260   ptr= (void*) (((char*) ptr)- WORD_LENGTH);
00261   register size_t s= *((size_t *) ptr);
00262   if (s<MAX_FAST) {
00263     ind(ptr)    = alloc_ptr(s);
00264     alloc_ptr(s)= ptr;
00265   }
00266   else {
00267     free (ptr);
00268     large_uses -= s;
00269   }
00270 }
00271 
00272 void*
00273 operator new[] (register size_t s) {
00274   register void* ptr;
00275   s= (s+ WORD_LENGTH+ WORD_LENGTH_INC)&WORD_MASK;
00276   if (s<MAX_FAST) {
00277     ptr= alloc_ptr(s);
00278     if (ptr==NULL) ptr= enlarge_malloc (s);
00279     else alloc_ptr(s)= ind(ptr);
00280   }
00281   else {
00282     ptr= safe_malloc (s);
00283     large_uses += s;
00284   }
00285   *((size_t *) ptr)=s;
00286   return (void*) (((char*) ptr)+ WORD_LENGTH);
00287 }
00288 
00289 void
00290 operator delete[] (register void* ptr) {
00291   ptr= (void*) (((char*) ptr)- WORD_LENGTH);
00292   register size_t s= *((size_t *) ptr);
00293   if (s<MAX_FAST) {
00294     ind(ptr)    = alloc_ptr(s);
00295     alloc_ptr(s)= ptr;
00296   }
00297   else {
00298     free (ptr);
00299     large_uses -= s;
00300   }
00301 }
00302 
00303 #endif // defined(X11TEXMACS) && (!defined(NO_FAST_ALLOC))