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

View File

@ -113,7 +113,7 @@ private:
_WX_DECLARE_BASEARRAY_2(T, name, name##_Predicate, classexp) _WX_DECLARE_BASEARRAY_2(T, name, name##_Predicate, classexp)
#define _WX_DECLARE_BASEARRAY_2(T, 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 Predicate; \
typedef predicate::CMPFUNC SCMPFUNC; \ typedef predicate::CMPFUNC SCMPFUNC; \

View File

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

View File

@ -1,30 +1,53 @@
#pragma once #pragma once
#include <limits> #include <limits>
#include <memory>
extern void _allocateHeap_wxString(); extern void _createHeap_wxString();
extern void _destroyHeap_wxString(); extern void _destroyHeap_wxString();
extern void* _allocHeap_wxString( size_t size ); extern void* _allocHeap_wxString( size_t size );
extern void* _reallocHeap_wxString( void* original, size_t size );
extern void _freeHeap_wxString( void* ptr ); 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 _destroyHeap_wxObject();
extern void* _allocHeap_wxObject( size_t size ); extern void* _allocHeap_wxObject( size_t size );
extern void* _reallocHeap_wxObject( void* original, size_t size );
extern void _freeHeap_wxObject( void* ptr ); 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> template<typename T>
class wxStringAllocator class wxStringAllocator
{ {
public : public :
// typedefs // typedefs
typedef T value_type; typedef T value_type;
typedef value_type* pointer; typedef value_type* pointer;
typedef const value_type* const_pointer; typedef const value_type* const_pointer;
typedef value_type& reference; typedef value_type& reference;
typedef const value_type& const_reference; typedef const value_type& const_reference;
typedef std::size_t size_type; typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
public : public :
// convert an allocator<T> to allocator<U> // convert an allocator<T> to allocator<U>
@ -37,7 +60,7 @@ public :
public : public :
wxStringAllocator() wxStringAllocator()
{ {
_allocateHeap_wxString(); _createHeap_wxString();
} }
~wxStringAllocator() ~wxStringAllocator()
@ -79,15 +102,14 @@ public :
// standard placement-new syntax to initialize the object: // standard placement-new syntax to initialize the object:
void construct(pointer p, const T& t) { new(p) T(t); } void construct(pointer p, const T& t) { new(p) T(t); }
// standard placement destructor: // 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&) { return true; }
bool operator!=(wxStringAllocator const& a) { return !operator==(a); } bool operator!=(wxStringAllocator const& a) { return !operator==(a); }
}; // end of class Allocator }; // end of class Allocator
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// // wxObjectAllocator
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
template<typename T> template<typename T>
class wxObjectAllocator class wxObjectAllocator
@ -95,13 +117,13 @@ class wxObjectAllocator
public : public :
// typedefs // typedefs
typedef T value_type; typedef T value_type;
typedef value_type* pointer; typedef value_type* pointer;
typedef const value_type* const_pointer; typedef const value_type* const_pointer;
typedef value_type& reference; typedef value_type& reference;
typedef const value_type& const_reference; typedef const value_type& const_reference;
typedef std::size_t size_type; typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
public : public :
// convert an allocator<T> to allocator<U> // convert an allocator<T> to allocator<U>
@ -114,7 +136,7 @@ public :
public : public :
wxObjectAllocator() wxObjectAllocator()
{ {
_allocateHeap_wxObject(); _createHeap_wxObject();
} }
~wxObjectAllocator() ~wxObjectAllocator()
@ -155,8 +177,9 @@ public :
// standard placement-new syntax to initialize the object: // standard placement-new syntax to initialize the object:
void construct(pointer p, const T& t) { new(p) T(t); } void construct(pointer p, const T& t) { new(p) T(t); }
// standard placement destructor: // 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&) { return true; }
bool operator!=(wxObjectAllocator const& a) { return !operator==(a); } bool operator!=(wxObjectAllocator const& a) { return !operator==(a); }

View File

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

View File

@ -59,7 +59,9 @@ wxStringInputStream::~wxStringInputStream()
{ {
#if wxUSE_UNICODE #if wxUSE_UNICODE
// Note: wx[W]CharBuffer uses malloc()/free() // 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 #endif
} }

View File

@ -179,7 +179,11 @@ bool wxTextFile::OnRead(const wxMBConv& conv)
} }
#endif // wxUSE_UNICODE #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 // 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". // For compilers that support precompilation, includes "wx.h".
#include "wx/wxprec.h" #include "wx/wxprec.h"
@ -26,7 +37,7 @@ static int win32_string_heap_refcount;
static HANDLE win32_object_heap = INVALID_HANDLE_VALUE; static HANDLE win32_object_heap = INVALID_HANDLE_VALUE;
static int win32_object_heap_refcount; static int win32_object_heap_refcount;
void _allocateHeap_wxString() void _createHeap_wxString()
{ {
if( win32_string_heap == INVALID_HANDLE_VALUE ) 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 ); 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 ) void _freeHeap_wxString( void* ptr )
{ {
HeapFree( win32_string_heap, 0, 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 ) 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 ); 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 ) void _freeHeap_wxObject( void* ptr )
{ {
HeapFree( win32_object_heap, 0, ptr ); HeapFree( win32_object_heap, 0, ptr );