DEV Community

Discussion on: Exploring the Use of C++ for Game Development

 
plotarmouredtitan profile image
PlotArmouredTitan • Edited

This is a version that uses std::allocator to pre-allocate memory before later constructing it for usage

#include "stdio.h"
#include "stdlib.h"
#include <chrono>
#include <iostream>
#include <string>
#include <memory>

class Person {
public:
    int age;
    Person(int age)
    {
        this->age = age;
    }
};

auto time_ms()
{
    return std::chrono::high_resolution_clock::now();
}

int run(int r, int s) {
    auto start = time_ms();
    int e = 0;

    for (int i = 0; i < r; i++) {
        Person* p = new Person(s);
        e += p->age;
        delete p; // only to avoid `out of memory` error
        // in fact, `delete` improves performance here
        // almost twice
    }
    auto end = time_ms();
    auto took = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    printf("Took : %lld ms  ", took.count());
    return took.count();
}

int run_alloc(int r, int s) {

    auto start = time_ms();

    std::allocator<Person> alloc;
    //allocate memory pool
    Person * memPool = alloc.allocate(r);

    int e = 0;

    for (int i = 0; i < r; i++) {
        //retrieve address from memory pool
        Person* p = memPool + i;

        //construct object
        alloc.construct(p, s);

        e += p->age;

        //destroy object
        alloc.destroy(p);
    }

    //deallocate memory pool
    alloc.deallocate(memPool, r);

    auto end = time_ms();
    auto took = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    printf("Alloc method Took : %lld ms\n", took.count());
    return took.count();
}
int run_alloc_reused(int r, int s) {

    auto start = time_ms();

    std::allocator<Person> alloc;
    Person* memAddr = alloc.allocate(1);

    int e = 0;

    for (int i = 0; i < r; i++) {
        Person* p = memAddr;

        alloc.construct(p, s);

        e += p->age;

        alloc.destroy(p);
    }

    alloc.deallocate(memAddr, r);

    auto end = time_ms();
    auto took = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    printf("Reused Alloc method Took : %lld ms\n", took.count());
    return took.count();
}


int main(int argc, char** argv) {

    /*
    int r = atoi(argv[1]);
    int s = atoi(argv[2]);

    printf("Inputs : %d %d\n", r, s);
    printf("Integer type size : %ld\n", sizeof(int));

    */

    int shouldRun = 1;

    while(shouldRun)
    {
        int r = 0;
        int s = 0;

        std::cout << "input r" << '\n';
        std::cin >> r;
        std::cout << "input s" << '\n';
        std::cin >> s;

        long long sum = 0;
        long long min = 1L << 32U;
        long long max = -1;

        long long sum2 = 0;
        long long min2 = 1L << 32U;
        long long max2 = -1;

        int ts = 10;
        for (int i = 0; i < ts; i++) {
            long long t = run(r, s);
            long long t2 = run_alloc(r, s);

            if (t < min) min = t;
            if (t > max) max = t;
            sum += t;

            if (t2 < min2) min2 = t2;
            if (t2 > max2) max2 = t2;
            sum2 += t2;
        }
        double avg = ((double)sum) / ts;
        double avg2 = ((double)sum2) / ts;
        printf("Min : %lld, max : %lld, average : %f\n", min, max, avg);
        printf("Min2 : %lld, max2 : %lld, average2 : %f\n", min2, max2, avg2);

        std::cout << "input 0 to exit, 1 to continue" << '\n';
        std::cin >> shouldRun;
    }
}
Enter fullscreen mode Exit fullscreen mode

Some other changes I made to the code

  • used std::chrono for measuring time because its cross-platform while the method you used was not

  • used std::iostream to handle inputing values at startup time instead of using main() arguments

Edit:made some corrections to the code

Edit2: also I think that allocation and deallocation shouldn't even be included in the time measurement since GC allocations and deallocations are likely done at startup time

Thread Thread
 
taqmuraz profile image
Taqmuraz

Sorry, I wasn't online. I appreciate your efforts, I am already reading your code

Thread Thread
 
taqmuraz profile image
Taqmuraz

Case with 'std::allocator' looks better than others, because it has abstraction over test case. I must test how fast it is and compare with other allocation tests. Probably I will update contents of my article. Thank you again for your code :)