From b6142f475c4c30d0572580487786ebb8387ab915 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Fri, 15 May 2015 17:40:41 +0200 Subject: [PATCH 1/2] micro optimizations --- arangod/Aql/ExecutionEngine.cpp | 4 +- arangod/Aql/Query.cpp | 2 +- arangod/RestHandler/RestCursorHandler.cpp | 3 +- lib/Basics/associative.cpp | 48 ++++++++++++----------- lib/Basics/associative.h | 12 ++++-- lib/ShapedJson/json-shaper.cpp | 2 +- 6 files changed, 40 insertions(+), 31 deletions(-) diff --git a/arangod/Aql/ExecutionEngine.cpp b/arangod/Aql/ExecutionEngine.cpp index ff40e1b126..1570e1382d 100644 --- a/arangod/Aql/ExecutionEngine.cpp +++ b/arangod/Aql/ExecutionEngine.cpp @@ -198,8 +198,8 @@ ExecutionEngine::~ExecutionEngine () { // shutdown can throw - ignore it in the destructor } - for (auto it = _blocks.begin(); it != _blocks.end(); ++it) { - delete (*it); + for (auto& it : _blocks) { + delete it; } } diff --git a/arangod/Aql/Query.cpp b/arangod/Aql/Query.cpp index 0d40c44d45..427e39effb 100644 --- a/arangod/Aql/Query.cpp +++ b/arangod/Aql/Query.cpp @@ -138,7 +138,7 @@ void Profile::enter (ExecutionState state) { TRI_json_t* Profile::toJson (TRI_memory_zone_t*) { triagens::basics::Json result(triagens::basics::Json::Object); - for (auto& it : results) { + for (auto const& it : results) { result.set(StateNames[static_cast(it.first)].c_str(), triagens::basics::Json(it.second)); } return result.steal(); diff --git a/arangod/RestHandler/RestCursorHandler.cpp b/arangod/RestHandler/RestCursorHandler.cpp index 59eb67806b..4504995fbf 100644 --- a/arangod/RestHandler/RestCursorHandler.cpp +++ b/arangod/RestHandler/RestCursorHandler.cpp @@ -265,7 +265,8 @@ triagens::basics::Json RestCursorHandler::buildExtra (triagens::aql::QueryResult /// /// - *batchSize*: maximum number of result documents to be transferred from /// the server to the client in one roundtrip (optional). If this attribute is -/// not set, a server-controlled default value will be used. +/// not set, a server-controlled default value will be used. A *batchSize* value of +/// *0* is disallowed. /// /// - *ttl*: an optional time-to-live for the cursor (in seconds). The cursor will be /// removed on the server automatically after the specified amount of time. This diff --git a/lib/Basics/associative.cpp b/lib/Basics/associative.cpp index e80dabc9ed..cab6b4b802 100644 --- a/lib/Basics/associative.cpp +++ b/lib/Basics/associative.cpp @@ -755,12 +755,11 @@ void* TRI_LookupByKeyAssociativePointer (TRI_associative_pointer_t* array, void* TRI_LookupByElementAssociativePointer (TRI_associative_pointer_t* array, void const* element) { - uint64_t hash; - uint64_t i; - // compute the hash - hash = array->hashElement(array, element); - i = hash % array->_nrAlloc; + uint64_t const hash = array->hashElement(array, element); + uint64_t const n = array->_nrAlloc; + uint64_t i, k; + i = k = hash % n; #ifdef TRI_INTERNAL_STATS // update statistics @@ -768,11 +767,10 @@ void* TRI_LookupByElementAssociativePointer (TRI_associative_pointer_t* array, #endif // search the table - while (array->_table[i] != NULL && ! array->isEqualElementElement(array, element, array->_table[i])) { - i = TRI_IncModU64(i, array->_nrAlloc); -#ifdef TRI_INTERNAL_STATS - array->_nrProbesF++; -#endif + for (; i < n && array->_table[i] != nullptr && ! array->isEqualElementElement(array, element, array->_table[i]); ++i); + + if (i == n) { + for (i = 0; i < k && array->_table[i] != nullptr && ! array->isEqualElementElement(array, element, array->_table[i]); ++i); } // return whatever we found @@ -1231,19 +1229,22 @@ void TRI_FreeAssociativeSynced (TRI_memory_zone_t* zone, TRI_associative_synced_ void const* TRI_LookupByKeyAssociativeSynced (TRI_associative_synced_t* array, void const* key) { - uint64_t hash; - uint64_t i; void const* result; // compute the hash - hash = array->hashKey(array, key); + uint64_t const hash = array->hashKey(array, key); // search the table TRI_ReadLockReadWriteLock(&array->_lock); - i = hash % array->_nrAlloc; + uint64_t const n = array->_nrAlloc; + uint64_t i, k; - while (array->_table[i] != NULL && ! array->isEqualKeyElement(array, key, array->_table[i])) { - i = TRI_IncModU64(i, array->_nrAlloc); + i = k = hash % n; + + for (; i < n && array->_table[i] != nullptr && ! array->isEqualKeyElement(array, key, array->_table[i]); ++i); + + if (i == n) { + for (i = 0; i < k && array->_table[i] != nullptr && ! array->isEqualKeyElement(array, key, array->_table[i]); ++i); } result = array->_table[i]; @@ -1260,19 +1261,22 @@ void const* TRI_LookupByKeyAssociativeSynced (TRI_associative_synced_t* array, void const* TRI_LookupByElementAssociativeSynced (TRI_associative_synced_t* array, void const* element) { - uint64_t hash; - uint64_t i; void const* result; // compute the hash - hash = array->hashElement(array, element); + uint64_t const hash = array->hashElement(array, element); // search the table TRI_ReadLockReadWriteLock(&array->_lock); - i = hash % array->_nrAlloc; + uint64_t const n = array->_nrAlloc; + uint64_t i, k; - while (array->_table[i] != NULL && ! array->isEqualElementElement(array, element, array->_table[i])) { - i = TRI_IncModU64(i, array->_nrAlloc); + i = k = hash % n; + + for (; i < n && array->_table[i] != nullptr && ! array->isEqualElementElement(array, element, array->_table[i]); ++i); + + if (i == n) { + for (i = 0; i < k && array->_table[i] != nullptr && ! array->isEqualElementElement(array, element, array->_table[i]); ++i); } result = array->_table[i]; diff --git a/lib/Basics/associative.h b/lib/Basics/associative.h index 6761a36cf7..e9c3d3a2c8 100644 --- a/lib/Basics/associative.h +++ b/lib/Basics/associative.h @@ -411,14 +411,18 @@ T TRI_ProcessByKeyAssociativeSynced (TRI_associative_synced_t* array, void const* key, std::function callback) { // compute the hash - uint64_t hash = array->hashKey(array, key); + uint64_t const hash = array->hashKey(array, key); // search the table TRI_ReadLockReadWriteLock(&array->_lock); - uint64_t i = hash % array->_nrAlloc; + uint64_t const n = array->_nrAlloc; + uint64_t i, k; + i = k = hash % n; - while (array->_table[i] != NULL && ! array->isEqualKeyElement(array, key, array->_table[i])) { - i = TRI_IncModU64(i, array->_nrAlloc); + for (; i < n && array->_table[i] != nullptr && ! array->isEqualKeyElement(array, key, array->_table[i]); ++i); + + if (i == n) { + for (i = 0; i < k && array->_table[i] != nullptr && ! array->isEqualKeyElement(array, key, array->_table[i]); ++i); } T result = callback(array->_table[i]); diff --git a/lib/ShapedJson/json-shaper.cpp b/lib/ShapedJson/json-shaper.cpp index 2bfdf00ef5..e52a0177db 100644 --- a/lib/ShapedJson/json-shaper.cpp +++ b/lib/ShapedJson/json-shaper.cpp @@ -198,7 +198,7 @@ static bool EqualNameKeyAttributePath (TRI_associative_synced_t* array, char const* e = static_cast(element); TRI_shape_path_t const* ee = static_cast(element); - return TRI_EqualString(k,e + sizeof(TRI_shape_path_t) + ee->_aidLength * sizeof(TRI_shape_aid_t)); + return TRI_EqualString(k, e + sizeof(TRI_shape_path_t) + ee->_aidLength * sizeof(TRI_shape_aid_t)); } //////////////////////////////////////////////////////////////////////////////// From 77291a1e71d6209ec5f8c3307fd6650b8de119a5 Mon Sep 17 00:00:00 2001 From: Jan Steemann Date: Fri, 15 May 2015 19:05:06 +0200 Subject: [PATCH 2/2] split single shaper lock into multiple --- arangod/VocBase/voc-shaper.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/arangod/VocBase/voc-shaper.cpp b/arangod/VocBase/voc-shaper.cpp index e06b1a8ca6..2e632b20d4 100644 --- a/arangod/VocBase/voc-shaper.cpp +++ b/arangod/VocBase/voc-shaper.cpp @@ -30,6 +30,7 @@ #include "voc-shaper.h" #include "Basics/Exceptions.h" +#include "Basics/fasthash.h" #include "Basics/Mutex.h" #include "Basics/MutexLocker.h" #include "Basics/ReadLocker.h" @@ -67,9 +68,10 @@ typedef struct voc_shaper_s { TRI_document_collection_t* _collection; - triagens::basics::ReadWriteLock _accessorLock; triagens::basics::Mutex _shapeLock; triagens::basics::Mutex _attributeLock; + + triagens::basics::ReadWriteLock _accessorLock[8]; } voc_shaper_t; @@ -899,11 +901,12 @@ TRI_shape_access_t const* TRI_FindAccessorVocShaper (TRI_shaper_t* s, TRI_shape_pid_t pid) { TRI_shape_access_t search = { sid, pid, 0, nullptr }; + size_t const lockId = static_cast(fasthash64(&sid, sizeof(TRI_shape_sid_t), fasthash64(&pid, sizeof(TRI_shape_pid_t), 0x87654321)) % 8); voc_shaper_t* shaper = (voc_shaper_t*) s; TRI_shape_access_t const* found; { - READ_LOCKER(shaper->_accessorLock); + READ_LOCKER(shaper->_accessorLock[lockId]); found = static_cast(TRI_LookupByElementAssociativePointer(&shaper->_accessors, &search)); @@ -922,7 +925,8 @@ TRI_shape_access_t const* TRI_FindAccessorVocShaper (TRI_shaper_t* s, // acquire the write-lock and try to insert our own accessor { - WRITE_LOCKER(shaper->_accessorLock); + + WRITE_LOCKER(shaper->_accessorLock[lockId]); found = static_cast(TRI_InsertElementAssociativePointer(&shaper->_accessors, const_cast(static_cast(accessor)), false)); }