6660681: Incrementally reserve pages on win server 2003 for better large page affinity

Thu, 02 Oct 2008 12:01:08 -0700

author
jmasa
date
Thu, 02 Oct 2008 12:01:08 -0700
changeset 824
ee21eaa8ffe1
parent 812
ddfad9496151
child 825
cc68c8e9b309

6660681: Incrementally reserve pages on win server 2003 for better large page affinity
Summary: For windows server 2003 added option to reserve large pages individually.
Reviewed-by: alanb, jcoomes, tonyp, apetrusenko

src/os/linux/vm/globals_linux.hpp file | annotate | diff | comparison | revisions
src/os/solaris/vm/globals_solaris.hpp file | annotate | diff | comparison | revisions
src/os/windows/vm/globals_windows.hpp file | annotate | diff | comparison | revisions
src/os/windows/vm/os_windows.cpp file | annotate | diff | comparison | revisions
src/os/windows/vm/os_windows.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/globals.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/os/linux/vm/globals_linux.hpp	Wed Oct 01 15:05:06 2008 -0400
     1.2 +++ b/src/os/linux/vm/globals_linux.hpp	Thu Oct 02 12:01:08 2008 -0700
     1.3 @@ -38,5 +38,6 @@
     1.4  // platforms, but they may have different default values on other platforms.
     1.5  //
     1.6  define_pd_global(bool, UseLargePages, false);
     1.7 +define_pd_global(bool, UseLargePagesIndividualAllocation, false);
     1.8  define_pd_global(bool, UseOSErrorReporting, false);
     1.9  define_pd_global(bool, UseThreadPriorities, true) ;
     2.1 --- a/src/os/solaris/vm/globals_solaris.hpp	Wed Oct 01 15:05:06 2008 -0400
     2.2 +++ b/src/os/solaris/vm/globals_solaris.hpp	Thu Oct 02 12:01:08 2008 -0700
     2.3 @@ -44,5 +44,6 @@
     2.4  // platforms, but they may have different default values on other platforms.
     2.5  //
     2.6  define_pd_global(bool, UseLargePages, true);
     2.7 +define_pd_global(bool, UseLargePagesIndividualAllocation, false);
     2.8  define_pd_global(bool, UseOSErrorReporting, false);
     2.9  define_pd_global(bool, UseThreadPriorities, false);
     3.1 --- a/src/os/windows/vm/globals_windows.hpp	Wed Oct 01 15:05:06 2008 -0400
     3.2 +++ b/src/os/windows/vm/globals_windows.hpp	Thu Oct 02 12:01:08 2008 -0700
     3.3 @@ -37,5 +37,6 @@
     3.4  // platforms, but they may have different default values on other platforms.
     3.5  //
     3.6  define_pd_global(bool, UseLargePages, false);
     3.7 +define_pd_global(bool, UseLargePagesIndividualAllocation, true);
     3.8  define_pd_global(bool, UseOSErrorReporting, false);  // for now.
     3.9  define_pd_global(bool, UseThreadPriorities, true) ;
     4.1 --- a/src/os/windows/vm/os_windows.cpp	Wed Oct 01 15:05:06 2008 -0400
     4.2 +++ b/src/os/windows/vm/os_windows.cpp	Thu Oct 02 12:01:08 2008 -0700
     4.3 @@ -2593,9 +2593,104 @@
     4.4  }
     4.5  
     4.6  char* os::reserve_memory_special(size_t bytes) {
     4.7 -  DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
     4.8 -  char * res = (char *)VirtualAlloc(NULL, bytes, flag, PAGE_EXECUTE_READWRITE);
     4.9 -  return res;
    4.10 +
    4.11 +  if (UseLargePagesIndividualAllocation) {
    4.12 +    if (TracePageSizes && Verbose) {
    4.13 +       tty->print_cr("Reserving large pages individually.");
    4.14 +    }
    4.15 +    char * p_buf;
    4.16 +    // first reserve enough address space in advance since we want to be
    4.17 +    // able to break a single contiguous virtual address range into multiple
    4.18 +    // large page commits but WS2003 does not allow reserving large page space
    4.19 +    // so we just use 4K pages for reserve, this gives us a legal contiguous
    4.20 +    // address space. then we will deallocate that reservation, and re alloc
    4.21 +    // using large pages
    4.22 +    const size_t size_of_reserve = bytes + _large_page_size;
    4.23 +    if (bytes > size_of_reserve) {
    4.24 +      // Overflowed.
    4.25 +      warning("Individually allocated large pages failed, "
    4.26 +        "use -XX:-UseLargePagesIndividualAllocation to turn off");
    4.27 +      return NULL;
    4.28 +    }
    4.29 +    p_buf = (char *) VirtualAlloc(NULL,
    4.30 +                                 size_of_reserve,  // size of Reserve
    4.31 +                                 MEM_RESERVE,
    4.32 +                                 PAGE_EXECUTE_READWRITE);
    4.33 +    // If reservation failed, return NULL
    4.34 +    if (p_buf == NULL) return NULL;
    4.35 +
    4.36 +    release_memory(p_buf, bytes + _large_page_size);
    4.37 +    // round up to page boundary.  If the size_of_reserve did not
    4.38 +    // overflow and the reservation did not fail, this align up
    4.39 +    // should not overflow.
    4.40 +    p_buf = (char *) align_size_up((size_t)p_buf, _large_page_size);
    4.41 +
    4.42 +    // now go through and allocate one page at a time until all bytes are
    4.43 +    // allocated
    4.44 +    size_t  bytes_remaining = align_size_up(bytes, _large_page_size);
    4.45 +    // An overflow of align_size_up() would have been caught above
    4.46 +    // in the calculation of size_of_reserve.
    4.47 +    char * next_alloc_addr = p_buf;
    4.48 +
    4.49 +#ifdef ASSERT
    4.50 +    // Variable for the failure injection
    4.51 +    long ran_num = os::random();
    4.52 +    size_t fail_after = ran_num % bytes;
    4.53 +#endif
    4.54 +
    4.55 +    while (bytes_remaining) {
    4.56 +      size_t bytes_to_rq = MIN2(bytes_remaining, _large_page_size);
    4.57 +      // Note allocate and commit
    4.58 +      char * p_new;
    4.59 +
    4.60 +#ifdef ASSERT
    4.61 +      bool inject_error = LargePagesIndividualAllocationInjectError &&
    4.62 +          (bytes_remaining <= fail_after);
    4.63 +#else
    4.64 +      const bool inject_error = false;
    4.65 +#endif
    4.66 +
    4.67 +      if (inject_error) {
    4.68 +        p_new = NULL;
    4.69 +      } else {
    4.70 +        p_new = (char *) VirtualAlloc(next_alloc_addr,
    4.71 +                                    bytes_to_rq,
    4.72 +                                    MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES,
    4.73 +                                    PAGE_EXECUTE_READWRITE);
    4.74 +      }
    4.75 +
    4.76 +      if (p_new == NULL) {
    4.77 +        // Free any allocated pages
    4.78 +        if (next_alloc_addr > p_buf) {
    4.79 +          // Some memory was committed so release it.
    4.80 +          size_t bytes_to_release = bytes - bytes_remaining;
    4.81 +          release_memory(p_buf, bytes_to_release);
    4.82 +        }
    4.83 +#ifdef ASSERT
    4.84 +        if (UseLargePagesIndividualAllocation &&
    4.85 +            LargePagesIndividualAllocationInjectError) {
    4.86 +          if (TracePageSizes && Verbose) {
    4.87 +             tty->print_cr("Reserving large pages individually failed.");
    4.88 +          }
    4.89 +        }
    4.90 +#endif
    4.91 +        return NULL;
    4.92 +      }
    4.93 +      bytes_remaining -= bytes_to_rq;
    4.94 +      next_alloc_addr += bytes_to_rq;
    4.95 +    }
    4.96 +
    4.97 +    return p_buf;
    4.98 +
    4.99 +  } else {
   4.100 +    // normal policy just allocate it all at once
   4.101 +    DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
   4.102 +    char * res = (char *)VirtualAlloc(NULL,
   4.103 +                                      bytes,
   4.104 +                                      flag,
   4.105 +                                      PAGE_EXECUTE_READWRITE);
   4.106 +    return res;
   4.107 +  }
   4.108  }
   4.109  
   4.110  bool os::release_memory_special(char* base, size_t bytes) {
   4.111 @@ -2983,6 +3078,7 @@
   4.112  volatile intx os::win32::_os_thread_count    = 0;
   4.113  
   4.114  bool   os::win32::_is_nt              = false;
   4.115 +bool   os::win32::_is_windows_2003    = false;
   4.116  
   4.117  
   4.118  void os::win32::initialize_system_info() {
   4.119 @@ -3005,7 +3101,15 @@
   4.120    GetVersionEx(&oi);
   4.121    switch(oi.dwPlatformId) {
   4.122      case VER_PLATFORM_WIN32_WINDOWS: _is_nt = false; break;
   4.123 -    case VER_PLATFORM_WIN32_NT:      _is_nt = true;  break;
   4.124 +    case VER_PLATFORM_WIN32_NT:
   4.125 +      _is_nt = true;
   4.126 +      {
   4.127 +        int os_vers = oi.dwMajorVersion * 1000 + oi.dwMinorVersion;
   4.128 +        if (os_vers == 5002) {
   4.129 +          _is_windows_2003 = true;
   4.130 +        }
   4.131 +      }
   4.132 +      break;
   4.133      default: fatal("Unknown platform");
   4.134    }
   4.135  
   4.136 @@ -3103,9 +3207,13 @@
   4.137      NoYieldsInMicrolock = true;
   4.138    }
   4.139  #endif
   4.140 +  // This may be overridden later when argument processing is done.
   4.141 +  FLAG_SET_ERGO(bool, UseLargePagesIndividualAllocation,
   4.142 +    os::win32::is_windows_2003());
   4.143 +
   4.144    // Initialize main_process and main_thread
   4.145    main_process = GetCurrentProcess();  // Remember main_process is a pseudo handle
   4.146 -  if (!DuplicateHandle(main_process, GetCurrentThread(), main_process,
   4.147 + if (!DuplicateHandle(main_process, GetCurrentThread(), main_process,
   4.148                         &main_thread, THREAD_ALL_ACCESS, false, 0)) {
   4.149      fatal("DuplicateHandle failed\n");
   4.150    }
     5.1 --- a/src/os/windows/vm/os_windows.hpp	Wed Oct 01 15:05:06 2008 -0400
     5.2 +++ b/src/os/windows/vm/os_windows.hpp	Thu Oct 02 12:01:08 2008 -0700
     5.3 @@ -34,6 +34,7 @@
     5.4    static julong _physical_memory;
     5.5    static size_t _default_stack_size;
     5.6    static bool   _is_nt;
     5.7 +  static bool   _is_windows_2003;
     5.8  
     5.9   public:
    5.10    // Windows-specific interface:
    5.11 @@ -60,6 +61,9 @@
    5.12    // Tells whether the platform is NT or Windown95
    5.13    static bool is_nt() { return _is_nt; }
    5.14  
    5.15 +  // Tells whether the platform is Windows 2003
    5.16 +  static bool is_windows_2003() { return _is_windows_2003; }
    5.17 +
    5.18    // Returns the byte size of a virtual memory page
    5.19    static int vm_page_size() { return _vm_page_size; }
    5.20  
     6.1 --- a/src/share/vm/runtime/globals.hpp	Wed Oct 01 15:05:06 2008 -0400
     6.2 +++ b/src/share/vm/runtime/globals.hpp	Thu Oct 02 12:01:08 2008 -0700
     6.3 @@ -330,6 +330,12 @@
     6.4    product_pd(bool, UseLargePages,                                           \
     6.5            "Use large page memory")                                          \
     6.6                                                                              \
     6.7 +  product_pd(bool, UseLargePagesIndividualAllocation,                       \
     6.8 +          "Allocate large pages individually for better affinity")          \
     6.9 +                                                                            \
    6.10 +  develop(bool, LargePagesIndividualAllocationInjectError, false,           \
    6.11 +          "Fail large pages individual allocation")                         \
    6.12 +                                                                            \
    6.13    develop(bool, TracePageSizes, false,                                      \
    6.14            "Trace page size selection and usage.")                           \
    6.15                                                                              \

mercurial