2017-05-29 58 views
2

該任務是針對自定義分配器測量new的性能:Stack<size>。我認爲足夠的方法是測量分配給定大小的內存塊所需的時間。所選擇的範圍是:測量(自定義)分配器的執行時間?

  • 字節:100,1000,...,百萬

  • 塊數:20000,40000,...,200000

爲了測量newStack,下面的代碼被用於:

#include <iostream> 
#include <fstream> 
#include <sstream> 
#include <string> 
#include <vector> 
#include <cstddef>     // std::size_t 
#include <ctime>     // std::clock_t 

#include "MyStack.h" 

#define BLOCK_SIZE 100    // Test_Object size  

struct Measurement 
{ 
    Measurement(std::size_t n, double t): blocks_number(n), cpu_time(t) { } 

    std::size_t blocks_number; 
    double cpu_time; 
}; 

//---------------------------------------------------------------------------- 
class Test_Object 
{ 
    char data[BLOCK_SIZE]; 
}; 

//---------------------------------------------------------------------------- 
void sequential_deallocation(std::size_t number) 
{ 
    std::vector<Test_Object*> obj_arr(number + 1); 

    // allocate 
    for (std::size_t allocations = 0; allocations <= number; ++allocations) 
    { 
     obj_arr[allocations] = new Test_Object; 
    } 

    // deallocate in reverse order 
    for (std::size_t allocations = number; allocations-- > 0;) 
    { 
     delete obj_arr[allocations]; 
    } 
} 

//---------------------------------------------------------------------------- 
void time_test() 
{ 
    std::vector<Measurement> data; 

    for (std::size_t number = 20000; number <= 200000; number += 20000) // memory block number 
    { 
     std::clock_t start = std::clock(); 

     sequential_deallocation(number); 

     // find CPU execution time 
     double time = 1000.0 * (std::clock() - start)/CLOCKS_PER_SEC; 

     data.emplace_back(Measurement(number, time)); 
    } 

    std::string name("OperatorNewSize");  
    name += std::to_string(BLOCK_SIZE) + ".txt"; 
    write_to_file(name, data); // writes the contents of vector: data to file: name 
} 

//---------------------------------------------------------------------------- 

int main() 
try 
{ 
    // measure new 
    time_test(); 

    // measure Stack 
    const std::size_t number = 2500; 
    const std::size_t bytes = number * sizeof(Test_Object); 
    Stack<bytes> s; 

    std::vector<Test_Object*> obj_vect(number); 

    std::clock_t start = std::clock(); 
    for (std::size_t allocations = 0; allocations < number; ++allocations) 
    { 
     obj_vect[allocations] = reinterpret_cast<Test_Object*>(s.get(sizeof(Test_Object))); 
    } 


    for (std::size_t allocations = number; allocations-- > 0;) 
    { 
     s.free(); // not sure if right 
    } 

    double time = 1000.0 * (std::clock() - start)/CLOCKS_PER_SEC; 
    std::cout <<"Block Size: "<< BLOCK_SIZE <<"\tBlock Number: "<< number <<"\tTime: "<< time <<" [ms]\n"; 
} 
catch (std::exception& e) 
{ 
    std::cerr << e.what(); 
    getchar(); 
} 

我不知道,如果其實現方法具d我使用的是正確的,即編譯器優化了使時間測量無效的一部分代碼。我存儲持有矢量分配的內存的指針,我不知道這是否是正確的

我的主要問題是:

  • 是所描述的方法有效嗎?

  • 如何存儲容納分配內存的指針:vector,array?

  • 是測量Stack對不對?

  • 由於某種原因,我無法分配超過2500- 2600的內存 Test_Object s在 Stack,爲什麼? 回覆@ user4581301在下面的評論。

  • 有沒有一種方法可以自動化迭代整個內存塊的大小,這裏的變化範圍是#define BLOCK_SIZE 100;或指定Stack<size>大小的模板參數?


MyStack.h

#ifndef MyStack_h 
#define MyStack_h 

template <std::size_t N>          
class Stack 
{ 
    typedef unsigned char uchar; 
    typedef std::size_t uint; 

    uchar* data;             
    uchar* end;            
    uchar* top;            

    uint index; 
    uint memory_blocks_sizes[N];   // byte is the smallest memory unit 

    bool is_full() { return !(top < end); } 

    bool is_empty() { return top == data && index == 0; } 

    void update(uint n, bool allocate) 
    { 
     if (allocate) 
     { 
      top += n;      // shift top n bytes towards the end   
      memory_blocks_sizes[index] = n; // store size of allocated block 
      ++index;      // update index to store next 
     } 
     else 
     { 
      --index;      // update index to get previous 
      n = memory_blocks_sizes[index]; // get size of last allocated block 
      top -= n;      // shift top towards the start(data) 
     } 
    } 

public: 
    Stack() 
     : data(new uchar[N]), end(data + N), top(data), index(0) 
    { 

    } 

    ~Stack() { delete[] data; } 

    void* get(uint n) 
    { 
     if (is_full() || ((top + n) > end)) 
     { 
      throw std::bad_alloc("Stack::get()::Stack Overflow!\n"); 
     } 
     void* ret = (void*) top; 

     update(n, true); 

     return ret; 
    } 

    void free() 
    { 
     if (is_empty()) 
     { 
      throw std::bad_alloc("Stack::free()::Stack Underflow!\n"); 
     } 
     update(0, false); 
    } 

    uint available() const { return uint(end - top); }; 
}; 


#endif 
+1

你用'uint memory_blocks_sizes [N]'分配的內容是每個N至少有2個字節(可能是4或8個字節).' sizeof(Test_Object)'是100. Number是當前2500,所以N = 250000。這是至少500000字節,更可能是1或2 MB。 's'是自動變量,典型的自動存儲區域相對較小,1到10 MB。如果你想要一個更大的'Stack',你將不得不動態分配's',使'''靜態,或者說服操作系統爲你分配一個更大的自動數據存儲。 – user4581301

+0

@ user4581301如果您將評論轉換爲答案,它將被接受。 – Ziezi

回答

2

使用std::chrono從C++ 11,它是相當準確的。如果你的編譯器不支持它,你可以在windows上使用QueryPerformanceCounter

+2

我會考慮'QueryPerformanceCounter',謝謝! – Ziezi

+1

@Ziezi在附註中,如果您確實想要控制分配,請考慮實現自定義分配器:https://blog.molecular-matters.com/2012/08/14/memory-allocation-strategies-a-linear-allocator / – MattMatt2000