Memory managment



  • Hallo,

    Ich hab neulich ein Program geprofiled und bin zum Schluss gekommen, dass es ein Falschenhals bei dem Anlegen von kleinen Objekten hat. Um dem entgegen zu wirken will ich nun den operator new und den operator delete von dieser Klasse überladen. Ich bin so vorgegangen:

    template<class T, std::size_t max_plot>
    class MemManager
    {
    public:
      void*alloc()throw();
      void free(void*)throw();
      MemManager()throw();
    
    private:
      MemManager(const MemManager&);
      const MemManager&operator=(const MemManager&);
    
      char data_block[sizeof(T) * max_plot];
      void*free_data[max_plot];
      std::size_t free_data_num;
      std::size_t free_data_start;
      std::size_t free_data_end;
    
      static std::size_t next(std::size_t index)throw(){
        ++index;
        if(index == max_plot)
          index = 0;
        return index;
      }
    };
    
    template<class T, std::size_t max_plot>
    MemManager<T, max_plot>::MemManager()throw()
    {
      using std::size_t;
      for(size_t i=0; i<max_plot; ++i)
        free_data[i] = data_block + i * sizeof(T);
      free_data_num = max_plot;
      free_data_start = 0;
      free_data_end = 0;
    }
    
    template<class T, std::size_t max_plot>
    void*MemManager<T, max_plot>::alloc()throw()
    {
      using std::size_t;
      //check if we are out of memory
      if(free_data_num == 0)
        return NULL;
    
      //Get the next empty memory address
      void*data = free_data[free_data_start];
      free_data_start = next(free_data_start);
      --free_data_num;
      return data;
    }
    
    template<class T, size_t max_plot>
    void MemManager<T, max_plot>::free(void*data)throw()
    {
      using std::size_t;
      //check if the pointer belongs to this plot system
      assert(data_block <= data && data < data_block + sizeof(T)*max_plot);
    
      #ifndef NDEBUG
      //check if it has already been freed
      if(free_data_num != 0)
      {
        size_t i = free_data_start;
        do{
          assert(free_data[i] != data);
          i = next(i);
        }while(i != free_data_end);
      }
      #endif
      free_data[free_data_end] = data;
      free_data_end = next(free_data_end);
      ++free_data_num;
    }
    
    class A
    {
    public:
      int a;
    
      void*operator new(size_t size)
      {
        assert(size == sizeof(A));
        void*data = mem.alloc();
        if(data == NULL)
          throw std::bad_alloc();
        else
          return data;
      }
      void operator delete(void*data)
      {
        mem.free(data);
      }
    private:
      static MemManager<A, 256>mem;
    };
    
    MemManager<A, 256>A::mem;
    

    Da es das erste Mal ist, dass ich sowas mache wollte ich fragen ob ich das so stehen lassen kann. Wenn jemand Verbesserungsvorschläge (auch in Punkto Geschindigkeit) hat nur her damit.

    Desweiteren hätte ich ein paar Fragen bezüglich den Operatoren. Macht es einen Unterschied ob ich den operator new und operator delete static mache oder nicht? Wieso wird eine Größenangabe an den operator new übergeben? Ich meine er ist ja speziell nur für diese Klasse da also ist die Größe doch konstant. 😕


Log in to reply