Commit 52216a13 authored by Igor Kushnir's avatar Igor Kushnir

Make DUChainReferenceCounting instance inline function-local static

MSVC intentionally does not support DLL import/export of thread_local
variables. The result is the following compilation error:
C:\CI\Job Build\kdevplatform\serialization\referencecounting.h(57): error C2492:
'duchainReferenceCounting': data with thread storage duration may not have dll interface

In addition, this inline function-local static version unexpectedly
turned out to be much faster than the previous exported extern variable
version. The following table compares performance of the past, current
and considered alternative implementations in the affected benchmarks.
The numbers denote milliseconds per iteration.

version\benchmark       qhash   create  destroy shouldDo(-) shouldDo(+)
no thread_local         0.67    136     50      70          3146
bool thread_local       1.0     144     85      247         3294
exported thread_local   1.4     151     121     636         707
internal linkage        1.5     151     131     883         1025
non-inline f-l static   1.5     152     138     954         1060
inline variable         1.2     147     107     388         459
inline f-l static       1.2     149     103     212         318

        Legend
Benchmarks:
qhash       - BenchIndexedString::bench_qhashIndexedString()
create      - BenchIndexedString::bench_create()
destroy     - BenchIndexedString::bench_destroy()
shouldDo(-) - BenchItemRepository::shouldDoReferenceCounting(disabled)
shouldDo(+) - BenchItemRepository::shouldDoReferenceCounting(enabled)

Versions:
no thread_local         - 8fca91a0
bool thread_local       - db67d592
exported thread_local   - the version just before this commit
internal linkage        - static thread_local variable in the cpp file
non-inline f-l static   - instance() defined in the cpp file
inline variable         - inline thread_local variable in the header
inline f-l static       - this commit
parent 62a3f823
......@@ -20,9 +20,12 @@
*/
#include "referencecounting.h"
#include "itemrepository.h"
#include "debug.h"
#include <QMap>
#include <QAtomicInt>
#include "serialization/itemrepository.h"
#include <QThread>
namespace KDevelop {
......@@ -35,6 +38,7 @@ DUChainReferenceCounting::DUChainReferenceCounting()
, refCountingFirstRangeStart{nullptr}
, refCountingFirstRangeExtent{0u, 0u}
{
qCDebug(SERIALIZATION).nospace() << "Creating DUChainReferenceCounting(" << this << ") in " << QThread::currentThread();
}
void DUChainReferenceCounting::disableDUChainReferenceCounting(void* start)
......@@ -131,16 +135,14 @@ void DUChainReferenceCounting::enableDUChainReferenceCounting(void* start, unsig
#endif
}
thread_local DUChainReferenceCounting duchainReferenceCounting;
void enableDUChainReferenceCounting(void* start, unsigned int size)
{
duchainReferenceCounting.enableDUChainReferenceCounting(start, size);
DUChainReferenceCounting::instance().enableDUChainReferenceCounting(start, size);
}
void disableDUChainReferenceCounting(void* start)
{
duchainReferenceCounting.disableDUChainReferenceCounting(start);
DUChainReferenceCounting::instance().disableDUChainReferenceCounting(start);
}
}
......
......@@ -39,12 +39,19 @@ class KDEVPLATFORMSERIALIZATION_EXPORT DUChainReferenceCounting
{
Q_DISABLE_COPY(DUChainReferenceCounting)
public:
DUChainReferenceCounting();
bool shouldDoDUChainReferenceCounting(void* item) const;
void enableDUChainReferenceCounting(void* start, unsigned int size);
void disableDUChainReferenceCounting(void* start);
static DUChainReferenceCounting& instance()
{
static thread_local DUChainReferenceCounting duchainReferenceCounting;
return duchainReferenceCounting;
}
private:
DUChainReferenceCounting();
bool shouldDoDUChainReferenceCountingInternal(void* item) const;
bool doReferenceCounting;
......@@ -54,13 +61,11 @@ private:
QPair<uint, uint> refCountingFirstRangeExtent;
};
KDEVPLATFORMSERIALIZATION_EXPORT extern thread_local DUChainReferenceCounting duchainReferenceCounting;
KDEVPLATFORMSERIALIZATION_EXPORT void initReferenceCounting();
inline bool shouldDoDUChainReferenceCounting(void* item)
{
return duchainReferenceCounting.shouldDoDUChainReferenceCounting(item);
return DUChainReferenceCounting::instance().shouldDoDUChainReferenceCounting(item);
}
inline bool DUChainReferenceCounting::shouldDoDUChainReferenceCountingInternal(void* item) const
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment