0

Following this question I've found that std::list, forward_list in libstdc++ memory inefficient for smallish items. Is there any other competitive free implementation available in this case?

#include "malloc.h"
#include <forward_list>
#include <iomanip>
#include <iostream>
#include <list>
#include <memory>
#include <vector>

#define NUM_BYTES 1024
#define WIDTH 30

using namespace std;

struct Test {

    struct mallinfo before_alloc;
    struct mallinfo after_alloc;

    Test() {
        cout << setw(WIDTH) << "num bytes to be allocated " << NUM_BYTES
             << endl;
    }

    ~Test() { cout << "done!" << endl; }

    void singly_malloc() {

        before_alloc = mallinfo();
        void *chs[NUM_BYTES];
        for (int i = 0; i < NUM_BYTES; ++i) {
            chs[i] = malloc(sizeof(char));
        }

        after_alloc = mallinfo();
        cout << setw(WIDTH) << "actual singly_malloc "
             << (after_alloc.uordblks - before_alloc.uordblks) << endl;

        for (int i = 0; i < NUM_BYTES; ++i) {
            free(chs[i]);
        }
    }

    void bulk_malloc() {

        before_alloc = mallinfo();
        auto chs = malloc(sizeof(char) * NUM_BYTES);

        after_alloc = mallinfo();
        cout << setw(WIDTH) << "actual bulk_malloc "
             << (after_alloc.uordblks - before_alloc.uordblks) << endl;

        free(chs);
    }

    void singly_alloc() {

        before_alloc = mallinfo();
        shared_ptr<char> chs[NUM_BYTES];
        for (int i = 0; i < NUM_BYTES; ++i) {
            chs[i] = make_shared<char>();
        }

        after_alloc = mallinfo();
        cout << setw(WIDTH) << "actual singly_alloc "
             << (after_alloc.uordblks - before_alloc.uordblks) << endl;
    }

    void bulk_alloc() {

        before_alloc = mallinfo();
        vector<char> chs(NUM_BYTES);

        after_alloc = mallinfo();
        cout << setw(WIDTH) << "actual bulk_alloc "
             << (after_alloc.uordblks - before_alloc.uordblks) << endl;
    }

    void bulk_but_singly_alloc() {

        before_alloc = mallinfo();
        list<char> chs(NUM_BYTES);

        after_alloc = mallinfo();
        cout << setw(WIDTH) << "actual bulk_but_singly_alloc "
             << (after_alloc.uordblks - before_alloc.uordblks) << endl;
    }

    void bulk_but_singly_alloc2() {

        before_alloc = mallinfo();
        forward_list<char> chs(NUM_BYTES);

        after_alloc = mallinfo();
        cout << setw(WIDTH) << "actual bulk_but_singly_alloc2 "
             << (after_alloc.uordblks - before_alloc.uordblks) << endl;
    }
};

int main() {

    Test t;
    t.singly_malloc();
    t.bulk_malloc();
    t.singly_alloc();
    t.bulk_alloc();
    t.bulk_but_singly_alloc();
    t.bulk_but_singly_alloc2();
}
sof
  • 7,253
  • 13
  • 48
  • 74
  • 4
    The question you linked recommends using `std::vector` - what's wrong with that? – UnholySheep Apr 22 '20 at 17:26
  • Then how to handle frequently insert remove? – sof Apr 22 '20 at 17:27
  • 3
    `std::vector` should be your go-to container unless you have a specific reason to use something else. – Jesper Juhl Apr 22 '20 at 17:28
  • 4
    [cpp-benchmark-vector-list-deque](https://baptiste-wicht.com/posts/2012/12/cpp-benchmark-vector-list-deque.html) – Jarod42 Apr 22 '20 at 17:29
  • @sof `Then how to handle frequently insert remove?` only insert/remove to/from the back. – eerorika Apr 22 '20 at 17:33
  • 1
    @sof insert/remove at which part? Does the order of elements matter? Also, you are asking about "competitive implementation". What makes you think that its theoretically possible with the same guarantees? – Dan M. Apr 22 '20 at 17:33
  • At some point you'll sacrifice something. You can't have your cake and eat it. Said that, you may create a structure that works as linked list (and technically is) but allocates memory in chunks, as arrays, and your nodes are completely contained in those. All you would need is to keep two pointers at the beginning and keep track of allocated blocks (you may simply use a vector). One pointer is the head of the "real" list, and the other forms a list of free slots. It's over engineering IMO, and unnecessarily complicated, but I think goes well with your aim. – Oppen Apr 22 '20 at 18:25
  • Which is exactly what's suggested as an answer in the linked question. – Oppen Apr 22 '20 at 18:33

0 Answers0