[commit: ghc] arcpatch-D4679: RTS: Auto-size the allocation area depending on CPU cache size (a98f8a7)
git at git.haskell.org
git at git.haskell.org
Fri May 11 21:21:19 UTC 2018
Repository : ssh://git@git.haskell.org/ghc
On branch : arcpatch-D4679
Link : http://ghc.haskell.org/trac/ghc/changeset/a98f8a7dd2bae870c45570525182690122666e90/ghc
>---------------------------------------------------------------
commit a98f8a7dd2bae870c45570525182690122666e90
Author: Simon Jakobi <simon.jakobi at gmail.com>
Date: Fri May 11 17:20:58 2018 -0400
RTS: Auto-size the allocation area depending on CPU cache size
Summary:
Looks for L3 and L2 caches and sets the size of the allocation area
to the size of the largest cache found.
If we can't find anything, use the existing default of 1MB.
Implemented for Linux, Windows, and Darwin.
Tested on Linux and 64bit Windows only so far.
Reviewers: bgamari, erikd, simonmar
Subscribers: dfeuer, Phyx, AndreasK, rwbarton, thomie, carter
GHC Trac Issues: #13362
Differential Revision: https://phabricator.haskell.org/D4679
>---------------------------------------------------------------
a98f8a7dd2bae870c45570525182690122666e90
rts/RtsFlags.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
rts/ghc.mk | 10 ++++----
2 files changed, 81 insertions(+), 6 deletions(-)
diff --git a/rts/RtsFlags.c b/rts/RtsFlags.c
index 7c292d2..d000c49 100644
--- a/rts/RtsFlags.c
+++ b/rts/RtsFlags.c
@@ -33,6 +33,14 @@
#include <fs_rts.h>
+#if defined(mingw32_HOST_OS)
+#include <windows.h>
+#endif
+
+#if defined(darwin_HOST_OS)
+#include <sys/sysctl.h>
+#endif
+
// Flag Structure
RTS_FLAGS RtsFlags;
@@ -124,6 +132,8 @@ static void setProgName (char *argv[]);
static void errorRtsOptsDisabled (const char *s);
+static StgWord32 largestCpuCacheSize(void);
+
/* -----------------------------------------------------------------------------
* Command-line option parsing routines.
* ---------------------------------------------------------------------------*/
@@ -135,6 +145,10 @@ void initRtsFlagsDefaults(void)
if (maxStkSize == 0)
maxStkSize = 8 * 1024 * 1024;
+ StgWord32 minAllocAreaSize = largestCpuCacheSize();
+ if (minAllocAreaSize == 0)
+ minAllocAreaSize = 1024 * 1024;
+
RtsFlags.GcFlags.statsFile = NULL;
RtsFlags.GcFlags.giveStats = NO_GC_STATS;
@@ -143,7 +157,7 @@ void initRtsFlagsDefaults(void)
RtsFlags.GcFlags.stkChunkSize = (32 * 1024) / sizeof(W_);
RtsFlags.GcFlags.stkChunkBufferSize = (1 * 1024) / sizeof(W_);
- RtsFlags.GcFlags.minAllocAreaSize = (1024 * 1024) / BLOCK_SIZE;
+ RtsFlags.GcFlags.minAllocAreaSize = minAllocAreaSize / BLOCK_SIZE;
RtsFlags.GcFlags.largeAllocLim = 0; /* defaults to minAllocAreasize */
RtsFlags.GcFlags.nurseryChunkSize = 0;
RtsFlags.GcFlags.minOldGenSize = (1024 * 1024) / BLOCK_SIZE;
@@ -2235,6 +2249,67 @@ void freeRtsArgs(void)
freeRtsArgv();
}
+// Return the size in bytes of the largest L3 or L2 CPU cache on the system.
+// Returns 0 if the cache size can't be determined.
+static StgWord32 largestCpuCacheSize(void)
+{
+#if defined(linux_HOST_OS)
+ int args[2] = {
+ _SC_LEVEL3_CACHE_SIZE,
+ _SC_LEVEL2_CACHE_SIZE,
+ };
+ for (int i = 0; i < 2; i++) {
+ long size = sysconf(args[i]);
+ if (size > 0L)
+ return (StgWord32)size;
+ }
+#elif defined(mingw32_HOST_OS)
+ DWORD max_cache_size = 0;
+
+ DWORD buffer_size = 0;
+ // Determine the necessary buffer size
+ GetLogicalProcessorInformationEx(RelationCache, NULL, &buffer_size);
+
+ SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* buffer =
+ (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)malloc(buffer_size);
+
+ BOOL ok =
+ GetLogicalProcessorInformationEx(RelationCache, buffer, &buffer_size);
+ if (!ok)
+ sysErrorBelch("GetLogicalProcessorInformationEx failed");
+
+ // SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX is a variable-size structure, so
+ // we progress by adding the size of the current SLPIE to the pointer.
+ for (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX* p = buffer;
+ (char*)p < (char*)buffer + buffer_size;
+ p = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)
+ ((char*)p + p->Size)) {
+
+ if (p->Relationship == RelationCache) {
+ CACHE_RELATIONSHIP cache = p->Cache;
+ if ((cache.Type == CacheUnified || cache.Type == CacheData) &&
+ (cache.Level == 2 || cache.Level == 3) &&
+ cache.CacheSize > max_cache_size)
+ max_cache_size = cache.CacheSize;
+ } else
+ debugBelch("Unexpected Relationship %u", p->Relationship);
+ }
+ free(buffer);
+ return (StgWord32)max_cache_size;
+#elif defined(darwin_HOST_OS)
+ // TODO: The following code might also work on FreeBSD.
+ // Enable it if you can test it.
+ char* args[2] = { "hw.l3cachesize", "hw.l2cachesize" };
+ StgWord32 cache_size = 0;
+ size_t data_size = sizeof(cache_size);
+ for (int i = 0; i < 2; i++) {
+ int ret = sysctlbyname(args[i], &cache_size, &data_size, NULL, 0);
+ if (ret == 0 && cache_size > 0)
+ return cache_size;
+ }
+#endif
+ return 0;
+}
/*
Note [OPTION_SAFE vs OPTION_UNSAFE]
diff --git a/rts/ghc.mk b/rts/ghc.mk
index e96e147..95e602f 100644
--- a/rts/ghc.mk
+++ b/rts/ghc.mk
@@ -22,10 +22,10 @@ rts_VERSION = 1.0
# Minimum supported Windows version.
# These numbers can be found at:
# https://msdn.microsoft.com/en-us/library/windows/desktop/aa383745(v=vs.85).aspx
-# If we're compiling on windows, enforce that we only support Vista SP1+
+# If we're compiling on windows, enforce that we only support Windows 7 and newer.
# Adding this here means it doesn't have to be done in individual .c files
# and also centralizes the versioning.
-rts_WINVER = 0x06000100
+rts_WINVER = 0x0601
# merge GhcLibWays and GhcRTSWays but strip out duplicates
rts_WAYS = $(GhcLibWays) $(filter-out $(GhcLibWays),$(GhcRTSWays))
@@ -192,11 +192,10 @@ endif
rts_dist_$1_CC_OPTS += -DRtsWay=\"rts_$1\"
-# If we're compiling on windows, enforce that we only support XP+
-# Adding this here means it doesn't have to be done in individual .c files
-# and also centralizes the versioning.
+# Windows version requirement
ifeq "$$(TargetOS_CPP)" "mingw32"
rts_dist_$1_CC_OPTS += -DWINVER=$(rts_WINVER)
+rts_dist_$1_CC_OPTS += -D_WIN32_WINNT=$(rts_WINVER)
endif
ifneq "$$(UseSystemLibFFI)" "YES"
@@ -372,6 +371,7 @@ endif
# Set Windows version
ifeq "$$(TargetOS_CPP)" "mingw32"
rts_CC_OPTS += -DWINVER=$(rts_WINVER)
+rts_CC_OPTS += -D_WIN32_WINNT=$(rts_WINVER)
endif
#-----------------------------------------------------------------------------
More information about the ghc-commits
mailing list