reduce overhead on DCPacker construction and push/pop operations

This commit is contained in:
David Rose 2004-07-02 17:11:59 +00:00
parent 53e73a5014
commit 3ac771804b
3 changed files with 100 additions and 20 deletions

View File

@ -680,6 +680,19 @@ get_write_pointer(size_t size) {
return _pack_data.get_write_pointer(size);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::StackElement::get_num_stack_elements_ever_allocated
// Access: Published, Static
// Description: Returns the number of DCPacker::StackElement pointers
// ever simultaneously allocated; these are now either
// in active use or have been recycled into the deleted
// DCPacker::StackElement pool to be used again.
////////////////////////////////////////////////////////////////////
INLINE int DCPacker::
get_num_stack_elements_ever_allocated() {
return StackElement::_num_ever_allocated;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::raw_pack_int8
// Access: Published
@ -1138,3 +1151,37 @@ advance() {
_current_field = _current_parent->get_nested_field(_current_field_index);
}
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::StackElement::operator new
// Access: Public
// Description: Allocates the memory for a new DCPacker::StackElement.
// This is specialized here to provide for fast
// allocation of these things.
////////////////////////////////////////////////////////////////////
INLINE void *DCPacker::StackElement::
operator new(size_t size) {
if (_deleted_chain != (DCPacker::StackElement *)NULL) {
StackElement *obj = _deleted_chain;
_deleted_chain = _deleted_chain->_next;
return obj;
}
#ifndef NDEBUG
_num_ever_allocated++;
#endif // NDEBUG
return ::operator new(size);
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::StackElement::operator delete
// Access: Public
// Description: Frees the memory for a deleted DCPacker::StackElement.
// This is specialized here to provide for fast
// allocation of these things.
////////////////////////////////////////////////////////////////////
INLINE void DCPacker::StackElement::
operator delete(void *ptr) {
StackElement *obj = (StackElement *)ptr;
obj->_next = _deleted_chain;
_deleted_chain = obj;
}

View File

@ -24,6 +24,9 @@
#include "dcSwitchParameter.h"
#include "dcClass.h"
DCPacker::StackElement *DCPacker::StackElement::_deleted_chain = NULL;
int DCPacker::StackElement::_num_ever_allocated = 0;
////////////////////////////////////////////////////////////////////
// Function: DCPacker::Constructor
// Access: Published
@ -39,6 +42,7 @@ DCPacker() {
_live_catalog = NULL;
_pack_error = false;
_range_error = false;
_stack = NULL;
clear();
}
@ -99,7 +103,7 @@ end_pack() {
_mode = M_idle;
if (!_stack.empty() || _current_field != NULL || _current_parent != NULL) {
if (_stack != NULL || _current_field != NULL || _current_parent != NULL) {
_pack_error = true;
}
@ -192,7 +196,7 @@ end_unpack() {
_mode = M_idle;
if (!_stack.empty() || _current_field != NULL || _current_parent != NULL) {
if (_stack != NULL || _current_field != NULL || _current_parent != NULL) {
// This happens if we have not unpacked all of the fields.
// However, this is not an error if we have called seek() during
// the unpack session (in which case the _catalog will be
@ -313,7 +317,7 @@ seek(const string &field_name) {
// If we are seeking, we don't need to remember our current stack
// position.
_stack.clear();
clear_stack();
_current_field = entry._field;
_current_parent = entry._parent;
_current_field_index = entry._field_index;
@ -332,7 +336,7 @@ seek(const string &field_name) {
} else if (_mode == M_repack) {
nassertr(_catalog != (DCPackerCatalog *)NULL, false);
if (!_stack.empty() || _current_field != (DCPackerInterface *)NULL) {
if (_stack != NULL || _current_field != NULL) {
// It is an error to reseek while the stack is nonempty--that
// means we haven't finished packing the current field.
_pack_error = true;
@ -427,12 +431,13 @@ push() {
_pack_error = true;
} else {
StackElement element;
element._current_parent = _current_parent;
element._current_field_index = _current_field_index;
element._push_marker = _push_marker;
element._pop_marker = _pop_marker;
_stack.push_back(element);
StackElement *element = new StackElement;
element->_current_parent = _current_parent;
element->_current_field_index = _current_field_index;
element->_push_marker = _push_marker;
element->_pop_marker = _pop_marker;
element->_next = _stack;
_stack = element;
_current_parent = _current_field;
@ -521,7 +526,7 @@ pop() {
_pack_error = true;
}
if (_stack.empty()) {
if (_stack == NULL) {
// Unbalanced pop().
_pack_error = true;
@ -548,12 +553,15 @@ pop() {
}
_current_field = _current_parent;
_current_parent = _stack.back()._current_parent;
_current_field_index = _stack.back()._current_field_index;
_push_marker = _stack.back()._push_marker;
_pop_marker = _stack.back()._pop_marker;
_current_parent = _stack->_current_parent;
_current_field_index = _stack->_current_field_index;
_push_marker = _stack->_push_marker;
_pop_marker = _stack->_pop_marker;
_num_nested_fields = (_current_parent == NULL) ? 0 : _current_parent->get_num_nested_fields();
_stack.pop_back();
StackElement *next = _stack->_next;
delete _stack;
_stack = next;
}
advance();
@ -1093,7 +1101,7 @@ handle_switch(const DCSwitchParameter *switch_parameter) {
////////////////////////////////////////////////////////////////////
void DCPacker::
clear() {
_stack.clear();
clear_stack();
_current_field = NULL;
_current_parent = NULL;
_current_field_index = 0;
@ -1110,6 +1118,20 @@ clear() {
_root = NULL;
}
////////////////////////////////////////////////////////////////////
// Function: DCPacker::clear_stack
// Access: Private
// Description: Empties the stack.
////////////////////////////////////////////////////////////////////
void DCPacker::
clear_stack() {
while (_stack != (StackElement *)NULL) {
StackElement *next = _stack->_next;
delete _stack;
_stack = next;
}
}
#ifdef HAVE_PYTHON
////////////////////////////////////////////////////////////////////
// Function: DCPacker::pack_class_object

View File

@ -131,6 +131,8 @@ public:
INLINE char *get_write_pointer(size_t size);
PUBLISHED:
INLINE static int get_num_stack_elements_ever_allocated();
// The following methods are used only for packing (or unpacking)
// raw data into the buffer between packing sessions (e.g. between
// calls to end_pack() and the next begin_pack()).
@ -177,6 +179,7 @@ private:
INLINE void advance();
void handle_switch(const DCSwitchParameter *switch_parameter);
void clear();
void clear_stack();
#ifdef HAVE_PYTHON
void pack_class_object(const DCClass *dclass, PyObject *object);
@ -208,14 +211,22 @@ private:
class StackElement {
public:
// As an optimization, we implement operator new and delete here
// to minimize allocation overhead during push() and pop().
INLINE void *operator new(size_t size);
INLINE void operator delete(void *ptr);
const DCPackerInterface *_current_parent;
int _current_field_index;
size_t _push_marker;
size_t _pop_marker;
};
typedef pvector<StackElement> Stack;
StackElement *_next;
static StackElement *_deleted_chain;
static int _num_ever_allocated;
};
StackElement *_stack;
Stack _stack;
const DCPackerInterface *_current_field;
const DCPackerInterface *_current_parent;
int _current_field_index;