mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 08:44:19 -04:00
reduce overhead on DCPacker construction and push/pop operations
This commit is contained in:
parent
53e73a5014
commit
3ac771804b
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user