<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: pratheek87</title>
    <description>The latest articles on DEV Community by pratheek87 (@pratheek87).</description>
    <link>https://dev.to/pratheek87</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F716276%2Fef7a0f3e-9f84-423c-8cef-f5e26c8841fb.png</url>
      <title>DEV Community: pratheek87</title>
      <link>https://dev.to/pratheek87</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pratheek87"/>
    <language>en</language>
    <item>
      <title>Memory management techniques to reduce memory consumption and improve performance.</title>
      <dc:creator>pratheek87</dc:creator>
      <pubDate>Wed, 06 Oct 2021 09:54:31 +0000</pubDate>
      <link>https://dev.to/pratheek87/memory-management-techniques-to-reduce-memory-consumption-and-improve-performance-jgc</link>
      <guid>https://dev.to/pratheek87/memory-management-techniques-to-reduce-memory-consumption-and-improve-performance-jgc</guid>
      <description>&lt;p&gt;Every memory allocation comes with a overhead of book keeping data. Also, every memory request results in a call to the operating system. Imagine a scenario where you would need to create millions of tiny objects over the entire time of the application usage. In environments where memory is a serious constraint it could lead to application failures because of the memory consumed by the book keeping data. &lt;/p&gt;

&lt;p&gt;In this post, I would like to share a common technique used to handle memory management to address the above concerns.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key concepts:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Creating a memory pool with the required size. Future allocations would be made from this pool rather than directly allocating from the OS. This would also avoid memory consumed by book-keeping.&lt;/li&gt;
&lt;li&gt;Overload the new operator to handle memory allocation requests using this pool.&lt;/li&gt;
&lt;li&gt;Make the memory allocator class to be used across by multiple classes rather than individual classes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Code Snippet:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Write a class that creates a memory pool of required size.
The key function here is the createpool method that calls malloc to allocate memory of required size and creates a list of FreeList pointers.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class memallocator
{
public:
    memallocator(size_t reserve) : mReserve(reserve) {}

private:
    size_t mReserve;
    FreeList* mBegin = nullptr;
    stack&amp;lt;FreeList*&amp;gt; freeptrs;
public:

    void* allocate(size_t s)
    {
        if (mBegin == nullptr)
        {
            if (!freeptrs.empty())
            {
                void* ptr = freeptrs.top();
                freeptrs.pop();
                return ptr;
            }
            else
                createPool(s);
        }
        FreeList* pFreeList = mBegin;
        mBegin = mBegin-&amp;gt;next;

        return pFreeList;
    }

    void deallocate(void* ptr, size_t s)
    {
        freeptrs.push(reinterpret_cast&amp;lt;FreeList*&amp;gt;(ptr));
    }


    void createPool(size_t s)
    {
        int total_size = s * mReserve;
        FreeList* pMem = reinterpret_cast&amp;lt;FreeList*&amp;gt;(malloc(total_size));
        FreeList* temp = pMem;

        //Create the list of pointers.
        for (auto i = 0; i &amp;lt; mReserve-1; ++i)
        {
            temp-&amp;gt;next = reinterpret_cast&amp;lt;FreeList*&amp;gt;(reinterpret_cast&amp;lt;char*&amp;gt;(temp) + s);
            temp = temp-&amp;gt;next;
        }

        temp-&amp;gt;next = nullptr;
        mBegin = pMem;
    }
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FreeList is defined as a struct below that would be used to keep track of the next pointer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;struct FreeList
{
    FreeList* next;
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;In the custom class overload the new and delete operators to make use of the new allocator we have created.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class MyCustomClass
{

    string mptrData;
    double d;

public:
    static memallocator allocator;
    MyCustomClass(const char* data, int s, double val) : d(val) {
        mptrData = data;
    }

    static void* operator new(size_t s)
    {
        return allocator.allocate(s);
    }

    static void operator delete(void* ptr, size_t s)
    {
        allocator.deallocate(ptr, s);
    }

    string sendData()
    {
        return mptrData + " " + to_string(d);
    }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The below code is needed to initialize the allocator object. We are reserving space for about 96000 objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;memallocator MyCustomClass::allocator{ 96000 }; // Reserve space for 24 objects.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;** Note **: 96000 was used for testing purposes only.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Let us write the main function to test
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int main()
{
    const char* data = "This is test object : ";
    long long int begin = GetTickCount64();

    for (auto i = 0; i &amp;lt; 240000; ++i)
    {
        auto* mc = new MyCustomClass(data, strlen(data), i);
    }

    long long int end = GetTickCount64();
    double elapsed = (end - begin);

    cout &amp;lt;&amp;lt; "Time measured: %.9f miliseconds.\n" &amp;lt;&amp;lt;  elapsed &amp;lt;&amp;lt; endl;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h6&gt;
  
  
  Key takeaways:
&lt;/h6&gt;

&lt;ol&gt;
&lt;li&gt;When tested with the memory allocator we have written along with the default we could see that our memory allocator was efficient slightly with time (since my CPU is quite powerful I guess :) ) but very efficient in terms of the memory consumed.
For the above sample it was around &lt;strong&gt;10K less taken by our memory allocator&lt;/strong&gt;  which is quite a decent gain.&lt;/li&gt;
&lt;li&gt;This is not industry standard approach rather a simple technique that needs to be customized for specific requirements.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Please reach out to me for any further questions.&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>memorymanagement</category>
      <category>programming</category>
      <category>performance</category>
    </item>
    <item>
      <title>C++ - Handling memory allocation failures when using the new operator.</title>
      <dc:creator>pratheek87</dc:creator>
      <pubDate>Thu, 30 Sep 2021 08:17:50 +0000</pubDate>
      <link>https://dev.to/pratheek87/c-handling-memory-allocation-failures-3lb1</link>
      <guid>https://dev.to/pratheek87/c-handling-memory-allocation-failures-3lb1</guid>
      <description>&lt;h1&gt;
  
  
  The below code is to demonstrate how to handle memory allocation failures when creating objects of custom class as well as existing data types.
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Key concepts:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Using the set_new_handler function.&lt;/li&gt;
&lt;li&gt;Global handlers vs class specific handlers to handle memory allocation failures.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  set_new_handler function
&lt;/h2&gt;

&lt;p&gt;The set_new_handler method is used to set/change the custom handler function invoked when there are memory allocation failures. If not set, the new operator invokes the default handler on failure which eventually throws bad allocation error.&lt;/p&gt;

&lt;h6&gt;
  
  
  Syntax:
&lt;/h6&gt;

&lt;p&gt;new_handler set_new_handler(new_handler p) throw();&lt;/p&gt;

&lt;h6&gt;
  
  
  Parameter:
&lt;/h6&gt;

&lt;p&gt;A funtion poiner that receives and returns nothing.&lt;/p&gt;

&lt;h6&gt;
  
  
  Return value:
&lt;/h6&gt;

&lt;p&gt;The value of the current new - handler function if this has already been set by this function previously, or a null&lt;br&gt;
pointer if this is the first call to set_new_handler(or if it was reset by a previous call).&lt;/p&gt;
&lt;h6&gt;
  
  
  Note:
&lt;/h6&gt;

&lt;p&gt;new_handler is a typedef for a function pointer that receives and returns nothing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Global handlers vs class specific handlers
&lt;/h2&gt;
&lt;h2&gt;
  
  
  Code Snippet:
&lt;/h2&gt;

&lt;p&gt;The below functions are used as handlers for global allocation and class object allocation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//Global
void nomemory()
{
    cerr &amp;lt;&amp;lt; "No memory available" &amp;lt;&amp;lt; endl;
    throw bad_alloc();
}

//Class object
void ctest_nomemory()
{
    cerr &amp;lt;&amp;lt; "No memory available for allocating the class object" &amp;lt;&amp;lt; endl;
    throw bad_alloc();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The below test class overloads the new operator.&lt;br&gt;
The currentHandler member points to the function that needs to be invoked when the allocation fails for this class.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class CTest
{
public:
    static new_handler set_new_handler(new_handler p);
    static void* operator new(size_t s);

private:
    static new_handler currHandler;

    double x[100000000];
    double x1[100000000];
    double x2[100000000];
    double x3[100000000];
    double x4[100000000];
};

//The below function overrides the std::set_new_handler method.
//The function returns the existing handler method and sets the 
//passed function as the new handler.
new_handler CTest::set_new_handler(new_handler p)
{
    new_handler old_handler = currHandler;
    currHandler = p;
    return old_handler;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The below function overloads the new operator.&lt;br&gt;
The std::set_new_handler function sets the global handler. &lt;br&gt;
The function later sets the old handler back before the function exits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;void* CTest::operator new(size_t s)
{
    new_handler global_handler = std::set_new_handler(currHandler);

    void* memory;
    try
    {
        memory = ::operator new(s);
    }
    catch (std::bad_alloc&amp;amp;)
    {
        std::set_new_handler(global_handler);
        throw;
    }
    std::set_new_handler(global_handler);

    return memory;
}

//Initialize the static object 
new_handler CTest::currHandler;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the main method first we can see the usage of the global handler and the next snippet for the class object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;int main()
{
    //Sets the global new handler.
    set_new_handler(nomemory);

    try
    {
        for (; ; )
            double* d = new double[100000000];
    }
    catch (bad_alloc)
    {
        cout &amp;lt;&amp;lt; "allocation failed" &amp;lt;&amp;lt; endl;
    }

    //Sets the class CTest new handler.
    CTest::set_new_handler(ctest_nomemory);
    try {
        CTest* testObj = new CTest;
    }
    catch (std::bad_alloc&amp;amp;)
    {
        cout &amp;lt;&amp;lt; "allocation failed" &amp;lt;&amp;lt; endl;
    }

    return 1;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Output:
&lt;/h2&gt;

&lt;p&gt;No memory available&lt;br&gt;
allocation failed&lt;/p&gt;

&lt;p&gt;No memory available for allocating the class object&lt;br&gt;
allocation failed&lt;/p&gt;

</description>
      <category>cpp</category>
      <category>new</category>
      <category>operatoroverloading</category>
      <category>allocationfailure</category>
    </item>
  </channel>
</rss>
