Changeset: 9682c557c929 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=9682c557c929
Modified Files:
gdk/gdk_utils.c
Branch: Feb2013
Log Message:
Use atomic operations to count memory use.
This implies no explicit locking.
Implemented for both GNU and Micorsoft compilers with a fallback using
locks for other compilers.
diffs (truncated from 332 to 300 lines):
diff --git a/gdk/gdk_utils.c b/gdk/gdk_utils.c
--- a/gdk/gdk_utils.c
+++ b/gdk/gdk_utils.c
@@ -313,10 +313,98 @@ int GDK_vm_trim = 1;
} while (0)
#endif
-static volatile size_t GDK_mallocedbytes_estimate = 0;
-static volatile size_t GDK_vm_cursize = 0;
-
+/* This block is to provide atomic addition and subtraction to select
+ * variables. We use intrinsic functions (recognized and inlined by
+ * the compiler) for both the GNU C compiler and Microsoft Visual
+ * Studio. By doing this, we avoid locking overhead. There is also a
+ * fall-back for other compilers. */
+#if defined(__GNUC__)
+#if SIZEOF_SSIZE_T == SIZEOF_LONG_LONG
+static volatile long long GDK_mallocedbytes_estimate = 0;
+static volatile long long GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile long long GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile long long GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
+#define ATOMIC_ADD(var, val) __sync_add_and_fetch(&var, (long long) (val))
+#define ATOMIC_INC(var) __sync_add_and_fetch(&var, (long long)
1)
+#define ATOMIC_SUB(var, val) __sync_sub_and_fetch(&var, (long long) (val))
+#define ATOMIC_DEC(var) __sync_sub_and_fetch(&var, (long long)
1)
+#else
+static volatile long GDK_mallocedbytes_estimate = 0;
+static volatile long GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile long GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile long GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
+#define ATOMIC_ADD(var, val) __sync_add_and_fetch(&var, (long) (val))
+#define ATOMIC_INC(var) __sync_add_and_fetch(&var, (long) 1)
+#define ATOMIC_SUB(var, val) __sync_sub_and_fetch(&var, (long) (val))
+#define ATOMIC_DEC(var) __sync_sub_and_fetch(&var, (long) 1)
+#endif
+#define ATOMIC_START(func)
+#define ATOMIC_END(func)
+#define ATOMIC_INIT(func)
+#elif defined(_MSC_VER)
+#include <intrin.h>
+#if SIZEOF_SSIZE_T == SIZEOF___INT64
+static volatile __int64 GDK_mallocedbytes_estimate = 0;
+static volatile __int64 GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile __int64 GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile __int64 GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
+#define ATOMIC_ADD(var, val) _InterlockedExchangeAdd64(&var, (__int64) (val))
+#define ATOMIC_INC(var) _InterlockedIncrement64(&var)
+#define ATOMIC_SUB(var, val) _InterlockedExchangeAdd64(&var, -(__int64)
(val))
+#define ATOMIC_DEC(var) _InterlockedDecrement64(&var)
+#pragma intrinsic(_InterlockedExchangeAdd64)
+#pragma intrinsic(_InterlockedIncrement64)
+#pragma intrinsic(_InterlockedDecrement64)
+#else
+static volatile long GDK_mallocedbytes_estimate = 0;
+static volatile long GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile long GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile long GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
+#define ATOMIC_ADD(var, val) _InterlockedExchangeAdd(&var, (long) (val))
+#define ATOMIC_INC(var) _InterlockedIncrement(&var)
+#define ATOMIC_SUB(var, val) _InterlockedExchangeAdd(&var, -(long) (val))
+#define ATOMIC_DEC(var) _InterlockedDecrement(&var)
+#pragma intrinsic(_InterlockedExchangeAdd)
+#pragma intrinsic(_InterlockedIncrement)
+#pragma intrinsic(_InterlockedDecrement)
+#endif
+#define ATOMIC_START(func)
+#define ATOMIC_END(func)
+#define ATOMIC_INIT(func)
+#else
+static volatile ssize_t GDK_mallocedbytes_estimate = 0;
+static volatile ssize_t GDK_vm_cursize = 0;
+#ifdef GDK_VM_KEEPHISTO
+volatile ssize_t GDK_vm_nallocs[MAX_BIT] = { 0 };
+#endif
+#ifdef GDK_MEM_KEEPHISTO
+volatile ssize_t GDK_nmallocs[MAX_BIT] = { 0 };
+#endif
static MT_Lock mbyteslock;
+#define ATOMIC_ADD(var, val) var += (ssize_t) (val)
+#define ATOMIC_INC(var) var++
+#define ATOMIC_SUB(var, val) var -= (ssize_t) (val)
+#define ATOMIC_DEC(var) var--
+#define ATOMIC_START(func) MT_lock_set(&mbyteslock, func)
+#define ATOMIC_END(func) MT_lock_unset(&mbyteslock, func)
+#define ATOMIC_INIT(func) MT_lock_init(&mbyteslock, func)
+#endif
size_t _MT_pagesize = 0; /* variable holding memory size */
size_t _MT_npages = 0; /* variable holding page size */
@@ -432,9 +520,9 @@ GDKmem_inuse(void)
/* RAM/swapmem that Monet is really using now */
size_t mem_mallocedbytes_estimate;
- MT_lock_set(&mbyteslock, "GDKmem_inuse");
- mem_mallocedbytes_estimate = GDK_mallocedbytes_estimate;
- MT_lock_unset(&mbyteslock, "GDKmem_inuse");
+ ATOMIC_START("GDKmem_inuse");
+ mem_mallocedbytes_estimate = (size_t) GDK_mallocedbytes_estimate;
+ ATOMIC_END("GDKmem_inuse");
return mem_mallocedbytes_estimate;
}
@@ -445,127 +533,90 @@ GDKvm_cursize(void)
/* current Monet VM address space usage */
size_t vm_cursize;
- MT_lock_set(&mbyteslock, "GDKvm_cursize");
- vm_cursize = GDK_vm_cursize;
- MT_lock_unset(&mbyteslock, "GDKvm_cursize");
+ ATOMIC_START("GDKvm_cursize");
+ vm_cursize = (size_t) GDK_vm_cursize;
+ ATOMIC_END("GDKvm_cursize");
return vm_cursize + GDKmem_inuse();
}
-#ifdef GDK_VM_KEEPHISTO
-volatile ssize_t GDK_vm_nallocs[MAX_BIT] = { 0 };
-#endif
#ifdef GDK_MEM_KEEPHISTO
-volatile ssize_t GDK_nmallocs[MAX_BIT] = { 0 };
-#endif
-
-static volatile int GDK_heapcheck_last = 0;
-
-static void
-GDKmem_heapcheck(int t)
-{
- /* correct heap estimate with the real thing */
- struct Mallinfo m = MT_mallinfo();
-
- GDK_mallocedbytes_estimate = (size_t) (m.usmblks + m.uordblks +
m.hblkhd);
- GDK_heapcheck_last = t;
-}
-
-#ifdef GDK_MEM_KEEPHISTO
-#define heapinc(_memdelta) \
- do { \
- int _idx; \
- \
- MT_lock_set(&mbyteslock, "heapinc"); \
- GDK_mallocedbytes_estimate += (_memdelta); \
- GDKmallidx(_idx, _memdelta); \
- GDK_nmallocs[_idx]++; \
- MT_lock_unset(&mbyteslock, "heapinc"); \
+#define heapinc(_memdelta) \
+ do { \
+ int _idx; \
+ \
+ ATOMIC_START("heapinc"); \
+ ATOMIC_ADD(GDK_mallocedbytes_estimate, _memdelta); \
+ GDKmallidx(_idx, _memdelta); \
+ ATOMIC_INC(GDK_nmallocs[_idx]); \
+ ATOMIC_END("heapinc"); \
} while (0)
#define heapdec(memdelta) \
do { \
- size_t _memdelta = (size_t) (memdelta); \
+ ssize_t _memdelta = (ssize_t) (memdelta); \
int _idx; \
\
- MT_lock_set(&mbyteslock, "heapdec"); \
- if (_memdelta > GDK_mallocedbytes_estimate) { \
- /* clearly, the stats are off: it should never \
- * become less-than-zero */ \
- GDKmem_heapcheck(GDKms()); \
- } else { \
- GDK_mallocedbytes_estimate -= _memdelta; \
- } \
+ ATOMIC_START("heapdec"); \
+ ATOMIC_SUB(GDK_mallocedbytes_estimate, _memdelta); \
GDKmallidx(_idx, _memdelta); \
- GDK_nmallocs[_idx]--; \
- MT_lock_unset(&mbyteslock, "heapdec"); \
+ ATOMIC_DEC(GDK_nmallocs[_idx]); \
+ ATOMIC_END("heapdec"); \
} while (0)
#else
-#define heapinc(_memdelta) \
- do { \
- MT_lock_set(&mbyteslock, "heapinc"); \
- GDK_mallocedbytes_estimate += (_memdelta); \
- MT_lock_unset(&mbyteslock, "heapinc"); \
+#define heapinc(_memdelta) \
+ do { \
+ ATOMIC_START("heapinc"); \
+ ATOMIC_ADD(GDK_mallocedbytes_estimate, _memdelta); \
+ ATOMIC_END("heapinc"); \
} while (0)
#define heapdec(memdelta) \
do { \
- size_t _memdelta = (size_t) (memdelta); \
- MT_lock_set(&mbyteslock, "heapdec"); \
- if (_memdelta > GDK_mallocedbytes_estimate) { \
- /* clearly, the stats are off: it should never \
- * become less-than-zero */ \
- GDKmem_heapcheck(GDKms()); \
- } else { \
- GDK_mallocedbytes_estimate -= _memdelta; \
- } \
- MT_lock_unset(&mbyteslock, "heapdec"); \
+ ssize_t _memdelta = (ssize_t) (memdelta); \
+ ATOMIC_START("heapdec"); \
+ ATOMIC_SUB(GDK_mallocedbytes_estimate, _memdelta); \
+ ATOMIC_END("heapdec"); \
} while (0)
#endif
#ifdef GDK_VM_KEEPHISTO
#define meminc(vmdelta, fcn) \
do { \
- size_t _vmdelta = (size_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
+ ssize_t _vmdelta = (ssize_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
int _idx; \
\
- MT_lock_set(&mbyteslock, fcn); \
+ ATOMIC_START(fcn); \
GDKmallidx(_idx, _vmdelta); \
- GDK_vm_nallocs[_idx]++; \
- GDK_vm_cursize += _vmdelta; \
- MT_lock_unset(&mbyteslock, fcn); \
+ ATOMIC_INC(GDK_vm_nallocs[_idx]); \
+ ATOMIC_ADD(GDK_vm_cursize, _vmdelta); \
+ ATOMIC_END(fcn); \
} while (0)
#define memdec(vmdelta, fcn) \
do { \
- size_t _vmdelta = (size_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
+ ssize_t _vmdelta = (ssize_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
int _idx; \
\
- MT_lock_set(&mbyteslock, fcn); \
+ ATOMIC_START(fcn); \
GDKmallidx(_idx, _vmdelta); \
- GDK_vm_nallocs[_idx]--; \
- if (_vmdelta > GDK_vm_cursize) \
- GDK_vm_cursize = 0; \
- else \
- GDK_vm_cursize -= _vmdelta; \
- MT_lock_unset(&mbyteslock, fcn); \
+ ATOMIC_DEC(GDK_vm_nallocs[_idx]); \
+ ATOMIC_SUB(GDK_vm_cursize, _vmdelta); \
+ ATOMIC_END(fcn); \
} while (0)
#else
#define meminc(vmdelta, fcn) \
do { \
- size_t _vmdelta = (size_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
+ ssize_t _vmdelta = (ssize_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
\
- MT_lock_set(&mbyteslock, fcn); \
- GDK_vm_cursize += _vmdelta; \
- MT_lock_unset(&mbyteslock, fcn); \
+ ATOMIC_START(fcn); \
+ ATOMIC_ADD(GDK_vm_cursize, _vmdelta); \
+ ATOMIC_END(fcn); \
} while (0)
#define memdec(vmdelta, fcn) \
do { \
- size_t _vmdelta = (size_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
+ ssize_t _vmdelta = (ssize_t) SEG_SIZE((vmdelta),MT_VMUNITLOG); \
\
- MT_lock_set(&mbyteslock, fcn); \
- if (_vmdelta > GDK_vm_cursize) \
- GDK_vm_cursize = 0; \
- else \
- GDK_vm_cursize -= _vmdelta; \
- MT_lock_unset(&mbyteslock, fcn); \
+ ATOMIC_START(fcn); \
+ ATOMIC_SUB(GDK_vm_cursize, _vmdelta); \
+ ATOMIC_END(fcn); \
} while (0)
#endif
@@ -589,28 +640,28 @@ GDKmemdump(void)
{
int i;
- MT_lock_set(&mbyteslock, "GDKmemdump");
+ ATOMIC_START("GDKmemdump");
THRprintf(GDKstdout, "#memory histogram\n");
for (i = 3; i < GDK_HISTO_MAX_BIT - 1; i++) {
size_t j = 1 << i;
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list