wxWidgets/MSW: Applied my custom string/object heap allocators to several more wxWidgets containers and types (helps reduce fragmentation and multi-threaded contention on the main heap).

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3100 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-05-28 16:24:53 +00:00
parent 4a2c5737c0
commit 6ec36fa37d
8 changed files with 125 additions and 46 deletions

View File

@ -13,8 +13,7 @@
#define _WX_BUFFER_H
#include "wx/wxchar.h"
#include <stdlib.h> // malloc() and free()
#include "wx/msw/HeapAllocator.h"
// ----------------------------------------------------------------------------
// Special classes for (wide) character strings: they use malloc/free instead
@ -31,13 +30,13 @@ public: \
} \
\
classname(size_t len) \
: m_str((chartype *)malloc((len + 1)*sizeof(chartype))) \
: m_str((chartype *)_allocHeap_wxString((len + 1)*sizeof(chartype))) \
{ \
m_str[len] = (chartype)0; \
} \
\
/* no need to check for NULL, free() does it */ \
~classname() { free(m_str); } \
~classname() { _freeHeap_wxString(m_str); } \
\
/* \
WARNING: \
@ -66,7 +65,7 @@ public: \
\
void reset() \
{ \
free(m_str); \
_freeHeap_wxString(m_str); \
m_str = NULL; \
} \
\
@ -77,14 +76,14 @@ public: \
\
classname& operator=(const chartype *str) \
{ \
free(m_str); \
_freeHeap_wxString(m_str); \
m_str = str ? strdupfunc(str) : NULL; \
return *this; \
} \
\
classname& operator=(const classname& src) \
{ \
free(m_str); \
_freeHeap_wxString(m_str); \
m_str = src.release(); \
\
return *this; \
@ -93,7 +92,7 @@ public: \
bool extend(size_t len) \
{ \
chartype * \
str = (chartype *)realloc(m_str, (len + 1)*sizeof(chartype)); \
str = (chartype *)_reallocHeap_wxString(m_str, (len + 1)*sizeof(chartype)); \
if ( !str ) \
return false; \
\
@ -124,14 +123,14 @@ public: \
}
#endif // wxABI_VERSION >= 20804
DEFINE_BUFFER(wxCharBuffer, char, wxStrdupA);
DEFINE_BUFFER(wxCharBuffer, char, _mswHeap_Strdup);
#if wxABI_VERSION >= 20804
DEFINE_WRITABLE_BUFFER(wxWritableCharBuffer, wxCharBuffer, char);
#endif
#if wxUSE_WCHAR_T
DEFINE_BUFFER(wxWCharBuffer, wchar_t, wxStrdupW);
DEFINE_BUFFER(wxWCharBuffer, wchar_t, _mswHeap_Strdup);
#if wxABI_VERSION >= 20804
DEFINE_WRITABLE_BUFFER(wxWritableWCharBuffer, wxWCharBuffer, wchar_t);
#endif
@ -173,10 +172,10 @@ public:
// everyting is private as it can only be used by wxMemoryBuffer
private:
wxMemoryBufferData(size_t size = wxMemoryBufferData::DefBufSize)
: m_data(size ? malloc(size) : NULL), m_size(size), m_len(0), m_ref(0)
: m_data(size ? _allocHeap_wxObject(size) : NULL), m_size(size), m_len(0), m_ref(0)
{
}
~wxMemoryBufferData() { free(m_data); }
~wxMemoryBufferData() { _freeHeap_wxObject(m_data); }
void ResizeIfNeeded(size_t newSize)
@ -184,10 +183,10 @@ private:
if (newSize > m_size)
{
void *dataOld = m_data;
m_data = realloc(m_data, newSize + wxMemoryBufferData::DefBufSize);
m_data = _reallocHeap_wxObject(m_data, newSize + wxMemoryBufferData::DefBufSize);
if ( !m_data )
{
free(dataOld);
_freeHeap_wxObject(dataOld);
}
m_size = newSize + wxMemoryBufferData::DefBufSize;

View File

@ -113,7 +113,7 @@ private:
_WX_DECLARE_BASEARRAY_2(T, name, name##_Predicate, classexp)
#define _WX_DECLARE_BASEARRAY_2(T, name, predicate, classexp) \
classexp name : public std::vector<T> \
classexp name : public std::vector< T,wxStringAllocator< T > > \
{ \
typedef predicate Predicate; \
typedef predicate::CMPFUNC SCMPFUNC; \

View File

@ -174,10 +174,10 @@ private:
}; \
\
VC6_WORKAROUND(elT, liT, decl) \
decl liT : public std::list<elT> \
decl liT : public std::list< elT, wxObjectAllocator< elT > > \
{ \
private: \
typedef std::list<elT> BaseListType; \
typedef std::list< elT, wxObjectAllocator< elT > > BaseListType; \
static BaseListType EmptyList; \
\
bool m_destroy; \
@ -187,7 +187,7 @@ private:
{ \
private: \
/* Workaround for broken VC6 nested class name resolution */ \
typedef std::list<elT>::iterator iterator; \
typedef std::list<elT, wxObjectAllocator< elT > >::iterator iterator; \
friend class liT; \
\
iterator m_iter; \

View File

@ -1,17 +1,40 @@
#pragma once
#include <limits>
#include <memory>
extern void _allocateHeap_wxString();
extern void _createHeap_wxString();
extern void _destroyHeap_wxString();
extern void* _allocHeap_wxString( size_t size );
extern void* _reallocHeap_wxString( void* original, size_t size );
extern void _freeHeap_wxString( void* ptr );
extern char* _mswHeap_Strdup( const char* src );
extern wchar_t* _mswHeap_Strdup( const wchar_t* src );
extern void _allocateHeap_wxObject();
extern void _createHeap_wxObject();
extern void _destroyHeap_wxObject();
extern void* _allocHeap_wxObject( size_t size );
extern void* _reallocHeap_wxObject( void* original, size_t size );
extern void _freeHeap_wxObject( void* ptr );
// _pxDestroy_ uses microsoft's internal definition for _Destroy(), found in xmemory;
// which suppresses a warning that we otherwise get. The warning appears to be specific
// to MSVC, so a basic _MSC_VER define will hopefully do the trick to allow support to
// non-Micrsoft compilers.
template<class T> inline
void _pxDestroy_(T* _Ptr)
{
#ifdef _MSC_VER
_Destroy( _Ptr );
#else
(_Ptr)->~T();
#endif
}
// --------------------------------------------------------------------------------------
// wxStringAllocator
// --------------------------------------------------------------------------------------
template<typename T>
class wxStringAllocator
{
@ -37,7 +60,7 @@ public :
public :
wxStringAllocator()
{
_allocateHeap_wxString();
_createHeap_wxString();
}
~wxStringAllocator()
@ -79,15 +102,14 @@ public :
// standard placement-new syntax to initialize the object:
void construct(pointer p, const T& t) { new(p) T(t); }
// standard placement destructor:
void destroy(pointer p) { p->~T(); }
void destroy(pointer p) { _pxDestroy_(p); }
bool operator==(wxStringAllocator const&) { return true; }
bool operator!=(wxStringAllocator const& a) { return !operator==(a); }
}; // end of class Allocator
// --------------------------------------------------------------------------------------
//
// wxObjectAllocator
// --------------------------------------------------------------------------------------
template<typename T>
class wxObjectAllocator
@ -114,7 +136,7 @@ public :
public :
wxObjectAllocator()
{
_allocateHeap_wxObject();
_createHeap_wxObject();
}
~wxObjectAllocator()
@ -155,8 +177,9 @@ public :
// standard placement-new syntax to initialize the object:
void construct(pointer p, const T& t) { new(p) T(t); }
// standard placement destructor:
void destroy(pointer p) { p->~T(); }
void destroy(pointer p) { _pxDestroy_(p); }
bool operator==(wxObjectAllocator const&) { return true; }
bool operator!=(wxObjectAllocator const& a) { return !operator==(a); }

View File

@ -436,13 +436,13 @@ public:
#if wxUSE_PRIVATE_HEAP && defined(__WXMSW__)
void* operator new( size_t size, const wxChar * = NULL, int = 0 )
{
_allocateHeap_wxObject();
_createHeap_wxObject();
return _allocHeap_wxObject( size );
}
void *operator new[] ( size_t size, const wxChar * = NULL, int = 0 )
{
_allocateHeap_wxObject();
_createHeap_wxObject();
return _allocHeap_wxObject( size );
}

View File

@ -59,7 +59,9 @@ wxStringInputStream::~wxStringInputStream()
{
#if wxUSE_UNICODE
// Note: wx[W]CharBuffer uses malloc()/free()
free(m_buf);
// PCSX2 : wx[W]CharBuffer now uses the wxString local heap! --air
//free(m_buf);
_freeHeap_wxString(m_buf);
#endif
}

View File

@ -179,7 +179,11 @@ bool wxTextFile::OnRead(const wxMBConv& conv)
}
#endif // wxUSE_UNICODE
free(buf.release()); // we don't need this memory any more
// we don't need this memory any more
// PCSX2 : So let's free it using the buffer object's API, instead of some idiotic
// low-level hack (bug found thanks to the use of custom heap allocation). --air
//free(buf.release());
buf.reset();
// now break the buffer in lines

View File

@ -1,3 +1,14 @@
// HeapAllocator.cpp
//
// Copyright 2009-2010 by the PCSX Dev Team.
// (under whatever license is appropriate for this sort of hack, I guess).
//
// Provides a specialized heap for wxStrings, which helps keep the main heap from being
// excessively fragmented/cluttered by billions of micro-sized string allocations. This
// should also improve multithreaded performace since strings can be allocated in parallel
// with other "common" allocation tasks on other threads.
//
// For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h"
@ -26,7 +37,7 @@ static int win32_string_heap_refcount;
static HANDLE win32_object_heap = INVALID_HANDLE_VALUE;
static int win32_object_heap_refcount;
void _allocateHeap_wxString()
void _createHeap_wxString()
{
if( win32_string_heap == INVALID_HANDLE_VALUE )
{
@ -45,13 +56,45 @@ void* _allocHeap_wxString( size_t size )
return (void*)HeapAlloc( win32_string_heap, 0, size );
}
void* _reallocHeap_wxString( void* original, size_t size )
{
if( !original )
return _allocHeap_wxString( size );
else
return (void*)HeapReAlloc( win32_string_heap, 0, original, size );
}
void _freeHeap_wxString( void* ptr )
{
HeapFree( win32_string_heap, 0, ptr );
}
void _allocateHeap_wxObject()
char* _mswHeap_Strdup( const char* src )
{
if( !src ) return NULL;
const size_t len = strlen(src);
char* retval = (char*)_allocHeap_wxString( len+1 );
if( !retval ) return NULL;
memcpy( retval, src, len+1 );
return retval;
}
wchar_t* _mswHeap_Strdup( const wchar_t* src )
{
if( !src ) return NULL;
const size_t len = (wcslen(src) + 1) * sizeof(wchar_t);
wchar_t* retval = (wchar_t*)_allocHeap_wxString( len );
if( !retval ) return NULL;
memcpy( retval, src, len );
return retval;
}
// --------------------------------------------------------------------------------------
//
// --------------------------------------------------------------------------------------
void _createHeap_wxObject()
{
if( win32_object_heap == INVALID_HANDLE_VALUE )
{
@ -70,6 +113,14 @@ void* _allocHeap_wxObject( size_t size )
return (void*)HeapAlloc( win32_object_heap, 0, size );
}
void* _reallocHeap_wxObject( void* original, size_t size )
{
if( !original )
return _allocHeap_wxObject( size );
else
return (void*)HeapReAlloc( win32_object_heap, 0, original, size );
}
void _freeHeap_wxObject( void* ptr )
{
HeapFree( win32_object_heap, 0, ptr );