Click here to Skip to main content
15,885,010 members
Articles / Programming Languages / C++

Session of low-level optimization of memory usage in C++ programs with total exposure

,
Rate me:
Please Sign up or sign in to vote.
5.00/5 (13 votes)
22 Jun 2009CPOL7 min read 39.6K   246   44  
In this article, we will try to make our algorithms work faster using the methods of low-level optimization of memory allocation in C++.
#ifndef CMN_FAST_OBJECTS_H
#define CMN_FAST_OBJECTS_H

// Change this constant if you have x64 architecture to 8
#ifndef MAKE_IT_FASTER_ALIGN_VALUE
#define MAKE_IT_FASTER_ALIGN_VALUE   4 
#endif

// common utils
namespace utils
{


//------------------------------------------
// CStaticAssert
//------------------------------------------
template <int iCanBeNonZero>
class CStaticAssert
{
public:
};

template <>
class CStaticAssert<0>
{
public:
    CStaticAssert()
    {
    }
    virtual void Error()=0;
};

#define DEF_STATIC_ASSERT(name, COND) \
       utils::CStaticAssert<(COND)> name; &name;   // to eliminate specific warning

//------------------------------------------
// native_cast
//------------------------------------------
template<class Result>
Result native_cast(Result result)
{
    return result;
}

} // utils


//------------------------------------------
// align utils: platform-specific part
//------------------------------------------
namespace align
{
    inline void * align_ptr(void * p)
    {
        if (!(((size_t)p)&(MAKE_IT_FASTER_ALIGN_VALUE-1)))
            return p;
        return (void*)((size_t)p + MAKE_IT_FASTER_ALIGN_VALUE - (((size_t)p)&(MAKE_IT_FASTER_ALIGN_VALUE-1)));
    }
    const int max_align_size = MAKE_IT_FASTER_ALIGN_VALUE;

} // align

//------------------------------------------
// fast object utils
//------------------------------------------
namespace utils
{

struct IManageable
{
    virtual ~IManageable(){}
    virtual void DestroyObject(void * pObject)=0;
    virtual void CreateAndSwap(void * pObject, int iMaxSize)=0;
    virtual void CreateAndCopy(void * pObject, int iMaxSize)=0;
};


// manageable control flags (iFlags field)
const int allow_std_swap = 1;
const int allow_copy     = 2;
const int allow_all      = 3;


// class manageable: wrapper, provides binary interface to manage object's life
template<class ImplType, int iFlags>
class manageable:public IManageable, public ImplType
{
    typedef manageable<ImplType, iFlags> ThisType;

    virtual void DestroyObject(void * pObject)
    {
        ((ThisType*)pObject)->~ThisType();
    }
    // CreateAndSwap
    template<int iFlags>
    void CreateAndSwapImpl(void * /*pObject*/, int /*iMaxSize*/)
    {
        throw std::runtime_error("Swap method is not supported");
    }

    template<>
    void CreateAndSwapImpl<allow_std_swap>(void * pObject, int /*iMaxSize*/)
    {
        ThisType * pNewObject = new(pObject)ThisType();
        pNewObject->swap(*this);
    }

    virtual void CreateAndSwap(void * pObject, int iMaxSize)
    {
        if (sizeof(ThisType)>iMaxSize)
            throw std::runtime_error("Object too large: swap method failed");
        CreateAndSwapImpl<iFlags & allow_std_swap>(pObject, iMaxSize);
    }

    // CreateAndCopy
    template<int iFlags>
    void CreateAndCopyImpl(void * /*pObject*/, int /*iMaxSize*/)
    {
        throw std::runtime_error("Copy method is not supported");
    }

    template<>
    void CreateAndCopyImpl<allow_copy>(void * pObject, int /*iMaxSize*/)
    {
        new(pObject)ThisType(*this);
    }

    virtual void CreateAndCopy(void * pObject, int iMaxSize)
    {
        if (sizeof(ThisType)>iMaxSize)
            throw std::runtime_error("Object too large: copy method failed");
        CreateAndCopyImpl<iFlags & allow_copy>(pObject, iMaxSize);
    }

public:
    manageable()
    {
    }
    template<class Type0>
    manageable(Type0 param0)
        : ImplType(param0)
    {
    }

};

// CObjectHolder: simple container for arbitrary manageable object
template<int iMaxSize>
class CObjectHolder
{
    char m_buffer[iMaxSize + align::max_align_size];
    IManageable * m_pManageable;
    void * m_pAlignedBuffer;

    template<class Type>
    void InitInterfaces(const Type & object)
    {
        ExtractInterface( object, &m_pManageable);
    }

    template<int iSizeOfObject>
    void Init()
    {
        if (!IsClean())
            Destroy();

        DEF_STATIC_ASSERT(small_size, iSizeOfObject <= iMaxSize);
        m_pAlignedBuffer = align::align_ptr(m_buffer);
    }

    void InitInterfacesByDelta(size_t iDelta)
    {
        ExtractInterfaceByDelta( iDelta, &m_pManageable);
    }

    void Destroy()
    {
        m_pManageable->DestroyObject(m_pAlignedBuffer);
        m_pManageable = 0;
        m_pAlignedBuffer = 0;
    }
    CObjectHolder(const CObjectHolder & );
    CObjectHolder & operator = (const CObjectHolder & );
public:
    CObjectHolder()
        : m_pManageable(0), m_pAlignedBuffer(0)
    {
    }
    template<class Type>
    void CreateByCopy(const Type & object)
    {
        Init<sizeof(object)>();
        new(m_pAlignedBuffer)Type(object);
        InitInterfaces(object);
    }
    template<class Type>
    void CreateBySwap(Type & object)
    {
        Init<sizeof(object)>();
        new(m_pAlignedBuffer)Type();
        ((Type*)(m_pAlignedBuffer))->swap(object);
        InitInterfaces(object);
    }
    void Copy(CObjectHolder<iMaxSize> * clean_object)
    {
        clean_object->Init<iMaxSize>();
        m_pManageable->CreateAndCopy(clean_object->m_pAlignedBuffer, iMaxSize);
        clean_object->InitInterfacesByDelta(GetInterfaceDelta(m_pManageable));
    }
    void Move(CObjectHolder<iMaxSize> * clean_object)
    {
        clean_object->Init<iMaxSize>();
        m_pManageable->CreateAndSwap(clean_object->m_pAlignedBuffer, iMaxSize);
        clean_object->InitInterfacesByDelta(GetInterfaceDelta(m_pManageable));

        m_pManageable = 0;
        m_pAlignedBuffer = 0;
    }
    template<class Type, class InterfaceType>
    void ExtractInterface(const Type & object, InterfaceType ** ppInterface)
    {
        size_t iDelta = (const char*)utils::native_cast<const InterfaceType*>(&object) - (const char*)&object;
        *ppInterface = (InterfaceType *)((char*)m_pAlignedBuffer + iDelta);
    }
    template<class InterfaceType>
    void ExtractInterfaceByDelta(size_t iDelta, InterfaceType ** ppInterface)
    {
        *ppInterface = (InterfaceType *)((char*)m_pAlignedBuffer + iDelta);
    }

    bool IsClean() const 
    {
        return m_pManageable==0;
    }

    size_t GetInterfaceDelta(void * pInterface) const 
    {
        if (!m_pAlignedBuffer)
            throw std::runtime_error("Cannot get interface from clean object");
        return (char*)pInterface - (char*)m_pAlignedBuffer;
    }
    ~CObjectHolder()
    {
        if (m_pManageable)
            Destroy();
    }
};

// CFastObject - holder with one public interface
template<int iMaxSize, class InterfaceType0>
class CFastObject
{
    typedef CObjectHolder<iMaxSize> HolderType;
    HolderType m_holder;
    InterfaceType0 * m_pInterface0;

    void InitInterface(size_t delta)
    {
        m_holder.ExtractInterfaceByDelta(delta, &m_pInterface0);
    }
public:
    // [managers]
    template<class Type>
    void CreateByCopy(const Type & object)
    {
        m_holder.CreateByCopy(object);
        m_holder.ExtractInterface(object, &m_pInterface0);
    }
    template<class Type>
    void CreateBySwap(Type & object)
    {
        m_holder.CreateBySwap(object);
        m_holder.ExtractInterface(object, &m_pInterface0);
    }
    // [clients]
    CFastObject()
        : m_pInterface0(0)
    {
    }

    void Copy(CFastObject<iMaxSize, InterfaceType0> * clean_object)
    {
        m_holder.Copy(&clean_object->m_holder);
        clean_object->InitInterface(m_holder.GetInterfaceDelta(m_pInterface0));
    }

    void Move(CFastObject<iMaxSize, InterfaceType0> * clean_object)
    {
        size_t delta = m_holder.GetInterfaceDelta(m_pInterface0);
        m_holder.Move(&clean_object->m_holder);
        clean_object->InitInterface(delta);
        m_pInterface0 = 0;
    }

    bool IsClean() const
    {
        return m_holder.IsClean();
    }
    // GetInterface
    template<class Type>
    Type * GetInterface()
    {
        DEF_STATIC_ASSERT(unknown_type, sizeof(object) <= iMaxSize);
    }
    template<>
    InterfaceType0 * GetInterface<InterfaceType0>()
    {
        return m_pInterface0;
    }

    InterfaceType0 * GetDefaultInterface()
    {
        return m_pInterface0;
    }

    InterfaceType0 * operator -> ()
    {
        return GetDefaultInterface();
    }
};


//--------------------------------
// typelist basics
//--------------------------------
template<class Head, class Tail>
struct Node
{
};
struct NullNode
{
};

template <class List>
struct GetMaxSize
{
};
template <class Head, class Tail>
struct GetMaxSize<Node<Head, Tail> >
{
    static const size_t TailSize = GetMaxSize<Tail>::Result;
    static const size_t Result = (TailSize > sizeof(Head) ) ? TailSize : sizeof(Head);
};
template <>
struct GetMaxSize<NullNode>
{
    static const size_t Result = 0;
};


} // utils

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Chief Technology Officer Apriorit Inc.
United States United States
ApriorIT is a software research and development company specializing in cybersecurity and data management technology engineering. We work for a broad range of clients from Fortune 500 technology leaders to small innovative startups building unique solutions.

As Apriorit offers integrated research&development services for the software projects in such areas as endpoint security, network security, data security, embedded Systems, and virtualization, we have strong kernel and driver development skills, huge system programming expertise, and are reals fans of research projects.

Our specialty is reverse engineering, we apply it for security testing and security-related projects.

A separate department of Apriorit works on large-scale business SaaS solutions, handling tasks from business analysis, data architecture design, and web development to performance optimization and DevOps.

Official site: https://www.apriorit.com
Clutch profile: https://clutch.co/profile/apriorit
This is a Organisation

33 members

Written By
Ukraine Ukraine
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions