Linux: Support transparent hugepages

Andrew Haley aph at redhat.com
Tue Jan 11 11:17:58 PST 2011


New Linux kernels have support for transparent hugepages: the kernel
automagically uses hugepages for all mappings of > 2M (or whatever) in
size.  This means that the UseLargePages option will not be needed in
future, and all Java apps will get the benefit of large pages.  This
will come as a great relief to anyone who has set up a Java app on a
Linux system to use large pages, which requires pages to be locked in
memory, root access, etc, etc.

The upstream kernel only has transparent hugepages for x86 (32 & 64),
but later it may apply to embedded powerpc and probably some other
architectures.

However, there is no guarantee that mmap() will produce 2M-aligned
mapped regions, even with requests that are a multiple of 2M in size,
so some small pages at the beginning and the end of each allocated
region remain.

This is fairly easy to fix with a patch like the one below.  However,
it doesn't use /proc/meminfo in the manner of os::large_page_init(),
and it only supports x86-64.  I'm not sure whether we ought to do this
for 32-bit x86, as it comsumes some address space.

So, do I need to use the page size finding logic from
os::large_page_init(), or should I simply use the default pages sizes
for each architecture?  The former seems rather excessive for this
purpose, but I'm happy to do it if you think that's necessary.

Comments welcome.

Thanks,
Andrew.


diff -r e24ab3fa6aaf src/os/linux/vm/os_linux.cpp
--- a/src/os/linux/vm/os_linux.cpp	Fri Jan 07 22:56:35 2011 -0800
+++ b/src/os/linux/vm/os_linux.cpp	Tue Jan 11 19:14:52 2011 +0000
@@ -2714,6 +2714,11 @@

  static address _highest_vm_reserved_address = NULL;

+#ifdef __x86_64__
+#define HPAGE_SIZE (2*1024*1024)
+#define GGC_QUIRE_SIZE 512
+#endif
+
  // If 'fixed' is true, anon_mmap() will attempt to reserve anonymous memory
  // at 'requested_addr'. If there are existing memory mappings at the same
  // location, however, they will be overwritten. If 'fixed' is false,
@@ -2735,6 +2740,26 @@
    addr = (char*)::mmap(requested_addr, bytes, PROT_READ|PROT_WRITE,
                         flags, -1, 0);

+#ifdef HPAGE_SIZE
+  if (requested_addr == NULL
+      && !(bytes & (HPAGE_SIZE-1))
+      && addr != MAP_FAILED
+      && ((size_t)addr & (HPAGE_SIZE-1))) {
+    char *mapped_region;
+    ::munmap(addr, bytes);
+    addr = (char *)::mmap (NULL, bytes + HPAGE_SIZE-1,
+			   PROT_READ | PROT_WRITE,
+			   flags, -1, 0);
+    mapped_region = addr;
+    addr = (char *)(((size_t)addr + HPAGE_SIZE-1)
+		    & ~(HPAGE_SIZE-1));
+    if (mapped_region != addr)
+      ::munmap(mapped_region, addr - mapped_region);
+    if (addr != mapped_region + HPAGE_SIZE-1)
+      ::munmap(addr + bytes, mapped_region + HPAGE_SIZE-1 - addr);
+  }
+#endif
+
    if (addr != MAP_FAILED) {
      // anon_mmap() should only get called during VM initialization,
      // don't need lock (actually we can skip locking even it can be called


More information about the hotspot-dev mailing list