Introduce a test of how much memory it takes to boot up V8.
authorerik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 1 Dec 2011 12:32:38 +0000 (12:32 +0000)
committererik.corry@gmail.com <erik.corry@gmail.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 1 Dec 2011 12:32:38 +0000 (12:32 +0000)
Linux only at the moment, since it uses /proc.  Shows that
there is room for improvement, espcially on 64 bit.
Review URL: http://codereview.chromium.org/8750001

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10122 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

test/cctest/test-mark-compact.cc

index 6379f3e..51409c2 100644 (file)
 
 #include <stdlib.h>
 
+#ifdef __linux__
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#endif
+
 #include "v8.h"
 
 #include "global-handles.h"
@@ -444,3 +452,84 @@ TEST(EmptyObjectGroups) {
   global_handles->AddImplicitReferences(
         Handle<HeapObject>::cast(object).location(), NULL, 0);
 }
+
+
+#ifdef __linux__
+
+
+static uintptr_t ReadLong(char* buffer, intptr_t* position, int base) {
+  char* end_address = buffer + *position;
+  uintptr_t result = strtoul(buffer + *position, &end_address, base);
+  CHECK(result != ULONG_MAX || errno != ERANGE);
+  CHECK(end_address > buffer + *position);
+  *position = end_address - buffer;
+  return result;
+}
+
+
+static intptr_t MemoryInUse() {
+  intptr_t memory_use = 0;
+
+  int fd = open("/proc/self/maps", O_RDONLY);
+  if (fd < 0) return -1;
+
+  const int kBufSize = 10000;
+  char buffer[kBufSize];
+  int length = read(fd, buffer, kBufSize);
+  intptr_t line_start = 0;
+  CHECK_LT(length, kBufSize);  // Make the buffer bigger.
+  CHECK_GT(length, 0);  // We have to find some data in the file.
+  while (line_start < length) {
+    if (buffer[line_start] == '\n') {
+      line_start++;
+      continue;
+    }
+    intptr_t position = line_start;
+    uintptr_t start = ReadLong(buffer, &position, 16);
+    CHECK_EQ(buffer[position++], '-');
+    uintptr_t end = ReadLong(buffer, &position, 16);
+    CHECK_EQ(buffer[position++], ' ');
+    CHECK(buffer[position] == '-' || buffer[position] == 'r');
+    bool read_permission = (buffer[position++] == 'r');
+    CHECK(buffer[position] == '-' || buffer[position] == 'w');
+    bool write_permission = (buffer[position++] == 'w');
+    CHECK(buffer[position] == '-' || buffer[position] == 'x');
+    bool execute_permission = (buffer[position++] == 'x');
+    CHECK(buffer[position] == '-' || buffer[position] == 'p');
+    bool private_mapping = (buffer[position++] == 'p');
+    CHECK_EQ(buffer[position++], ' ');
+    uintptr_t offset = ReadLong(buffer, &position, 16);
+    USE(offset);
+    CHECK_EQ(buffer[position++], ' ');
+    uintptr_t major = ReadLong(buffer, &position, 16);
+    USE(major);
+    CHECK_EQ(buffer[position++], ':');
+    uintptr_t minor = ReadLong(buffer, &position, 16);
+    USE(minor);
+    CHECK_EQ(buffer[position++], ' ');
+    uintptr_t inode = ReadLong(buffer, &position, 10);
+    while (position < length && buffer[position] != '\n') position++;
+    if ((read_permission || write_permission || execute_permission) &&
+        private_mapping && inode == 0) {
+      memory_use += (end - start);
+    }
+
+    line_start = position;
+  }
+  close(fd);
+  return memory_use;
+}
+
+
+TEST(BootUpMemoryUse) {
+  intptr_t initial_memory = MemoryInUse();
+  // Only Linux has the proc filesystem and only if it is mapped.  If it's not
+  // there we just skip the test.
+  if (initial_memory >= 0) {
+    InitializeVM();
+    intptr_t booted_memory = MemoryInUse();
+    CHECK_LE(booted_memory - initial_memory, 20 * 1024 * 1024);
+  }
+}
+
+#endif  // __linux__