Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

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

, , 22 Jun 2009 CPOL
In this article, we will try to make our algorithms work faster using the methods of low-level optimization of memory allocation in C++.
make-it-faster.zip
src
make_it_faster
make_it_faster_80.vcproj.DEV.ligen.user
alloc
win32
make_it_faster_win32
make_it_faster_win32_80.vcproj.DEV.ligen.user
win32_arena_local_sample
arena_local_sample_80.vcproj.DEV.ligen.user
win32_arena_sample
arena_sample_80.vcproj.DEV.ligen.user
win32_arena_tests
arena_tests_80.vcproj.DEV.ligen.user
win32_fast_object_sample
fast_object_sample_80.vcproj.DEV.ligen.user
#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)

Share

About the Authors

No Biography provided

Apriorit Inc
Apriorit Inc.
Ukraine Ukraine
ApriorIT is a Software Research and Development company that works in advanced knowledge-intensive scopes.
 
Company offers integrated research&development services for the software projects in such directions as Corporate Security, Remote Control, Mobile Development, Embedded Systems, Virtualization, Drivers and others.
 
Official site http://www.apriorit.com
Group type: Organisation

31 members

Follow on   LinkedIn

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150129.1 | Last Updated 23 Jun 2009
Article Copyright 2009 by Victor A. Milokum, Apriorit Inc
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid