From bcb46110b9a1685a2ba811e281a39e2ca1af5153 Mon Sep 17 00:00:00 2001 From: miker Date: Sat, 8 Dec 2007 19:03:52 +0000 Subject: [PATCH] Patch from Scott McKellar which adds a free-object-pool for jsonObjects, reducing malloc/free overhead by a large degree git-svn-id: svn://svn.open-ils.org/OpenSRF/trunk@1159 9efc2488-bf62-4759-914b-345cdb29e865 --- include/opensrf/osrf_json.h | 9 ++++- src/libopensrf/osrf_json_object.c | 83 +++++++++++++++++++++++++++++++++++---- 2 files changed, 82 insertions(+), 10 deletions(-) diff --git a/include/opensrf/osrf_json.h b/include/opensrf/osrf_json.h index 0f4f8cb..70fe09c 100644 --- a/include/opensrf/osrf_json.h +++ b/include/opensrf/osrf_json.h @@ -201,6 +201,11 @@ jsonObject* jsonNewBoolObject(int val); void jsonObjectFree( jsonObject* o ); /** + * Returns all unused jsonObjects to the heap + */ +void jsonObjectFreeUnused( void ); + +/** * Forces the given object to become an array (if it isn't already one) * and pushes the new object into the array */ @@ -223,7 +228,7 @@ char* jsonObjectToJSONRaw( const jsonObject* obj ); /** * Retrieves the object at the given key */ -jsonObject* jsonObjectGetKey( const jsonObject* obj, const char* key ); +jsonObject* jsonObjectGetKey( jsonObject* obj, const char* key ); const jsonObject* jsonObjectGetKeyConst( const jsonObject* obj, const char* key ); @@ -297,7 +302,7 @@ void jsonObjectSetNumber(jsonObject* dest, double num); void jsonObjectSetClass(jsonObject* dest, const char* classname ); const char* jsonObjectGetClass(const jsonObject* dest); -int jsonBoolIsTrue( jsonObject* boolObj ); +int jsonBoolIsTrue( const jsonObject* boolObj ); void jsonSetBool(jsonObject* bl, int val); diff --git a/src/libopensrf/osrf_json_object.c b/src/libopensrf/osrf_json_object.c index 64c8efd..6b2e0ad 100644 --- a/src/libopensrf/osrf_json_object.c +++ b/src/libopensrf/osrf_json_object.c @@ -14,6 +14,7 @@ GNU General Public License for more details. */ #include +#include #include #include @@ -39,17 +40,60 @@ GNU General Public License for more details. _obj_->value.l->freeItem = _jsonFreeListItem;\ } +static int unusedObjCapture = 0; +static int unusedObjRelease = 0; + +union unusedObjUnion{ + + union unusedObjUnion* next; + jsonObject obj; +}; +typedef union unusedObjUnion unusedObj; + +// We maintain a free list of jsonObjects that are available +// for use, in order to reduce the churning through +// malloc() and free(). + +static unusedObj* freeObjList = NULL; + static void add_json_to_buffer( const jsonObject* obj, growing_buffer * buf ); +/** + * Return all unused jsonObjects to the heap + * @return Nothing + */ +void jsonObjectFreeUnused( void ) { + + unusedObj* temp; + while( freeObjList ) { + temp = freeObjList->next; + free( freeObjList ); + freeObjList = temp; + } +} + jsonObject* jsonNewObject(const char* data) { jsonObject* o; - OSRF_MALLOC(o, sizeof(jsonObject)); - o->type = JSON_NULL; + + if( freeObjList ) { + o = (jsonObject*) freeObjList; + freeObjList = freeObjList->next; + unusedObjRelease++; + } + else + OSRF_MALLOC( o, sizeof(jsonObject) ); + + o->size = 0; + o->classname = NULL; + o->parent = NULL; if(data) { o->type = JSON_STRING; o->value.s = strdup(data); + } else { + o->type = JSON_NULL; + o->value.s = NULL; } return o; @@ -58,15 +102,28 @@ jsonObject* jsonNewObject(const char* data) { jsonObject* jsonNewObjectFmt(const char* data, ...) { jsonObject* o; - OSRF_MALLOC(o, sizeof(jsonObject)); - o->type = JSON_NULL; + + if( freeObjList ) { + o = (jsonObject*) freeObjList; + freeObjList = freeObjList->next; + } + else + OSRF_MALLOC( o, sizeof(jsonObject) ); + + o->size = 0; + o->classname = NULL; + o->parent = NULL; if(data) { VA_LIST_TO_STRING(data); o->type = JSON_STRING; o->value.s = strdup(VA_BUF); } - + else { + o->type = JSON_NULL; + o->value.s = NULL; + } + return o; } @@ -100,7 +157,17 @@ void jsonObjectFree( jsonObject* o ) { case JSON_ARRAY : osrfListFree(o->value.l); break; case JSON_STRING : free(o->value.s); break; } - free(o); + + // Stick the old jsonObject onto a free list + // for potential reuse + + unusedObj* unused = (unusedObj*) o; + unused->next = freeObjList; + freeObjList = unused; + + unusedObjCapture++; + if (unusedObjCapture > 1 && !(unusedObjCapture % 1000)) + osrfLogDebug( OSRF_LOG_MARK, "Reusable objects captured: %d, Objects reused: %d", unusedObjCapture, unusedObjRelease ); } static void _jsonFreeHashItem(char* key, void* item){ @@ -152,7 +219,7 @@ unsigned long jsonObjectSetKey( jsonObject* o, const char* key, jsonObject* newo return o->size; } -jsonObject* jsonObjectGetKey( const jsonObject* obj, const char* key ) { +jsonObject* jsonObjectGetKey( jsonObject* obj, const char* key ) { if(!(obj && obj->type == JSON_HASH && obj->value.h && key)) return NULL; return osrfHashGet( obj->value.h, key); } @@ -390,7 +457,7 @@ jsonObject* jsonObjectClone( const jsonObject* o ) { return result; } -int jsonBoolIsTrue( jsonObject* boolObj ) { +int jsonBoolIsTrue( const jsonObject* boolObj ) { if( boolObj && boolObj->type == JSON_BOOL && boolObj->value.b ) return 1; return 0; -- 2.11.0