Hi Bert,
I did a quick look into this problem. It seems V8 currently can't handle
such big heaps:
0) Memory allocator and MarkCompact garbage collector encode certain things
in a special way so without major rewriting you can try to get at most
~1.8gb heap on x64.
1) Memory management code is full of integer overflows --- it uses int where
bigger type is required to handle big heap sizes. [I am attaching small
dirty patch to fix some of this overflows. with it you can grow heap almost
up to 1.8 gb heap]
2) GC pauses will be huge for huge heaps: mark-sweep will take at > 1 s,
mark-compact will take > 3s, scavenge throughput will also be degraded (it
needs to scan oldspaces for intergenerational pointers).
--
Vyacheslav Egorov
On Wed, Aug 25, 2010 at 10:36 AM, Bert Belder <[email protected]> wrote:
> On Aug 25, 9:57 am, Erik Corry <[email protected]> wrote:
> > Are you running the 64 bit version of V8?
>
> I think so. To eliminate other causes I did a fresh git clone from
> git://github.com/v8/v8.git, then:
> scons arch=x64 sample=shell
> ./shell --max_old_space_size=2000000000 test.js
>
> > file `which v8`
> ./shell: ELF 64-bit LSB executable, x86-64, version 1 (SYSV),
> dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not
> stripped
>
> - Bert
>
> --
> v8-users mailing list
> [email protected]
> http://groups.google.com/group/v8-users
>
--
v8-users mailing list
[email protected]
http://groups.google.com/group/v8-users
diff --git a/src/heap.cc b/src/heap.cc
index ff92384..015918a 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -64,11 +64,11 @@ MapSpace* Heap::map_space_ = NULL;
CellSpace* Heap::cell_space_ = NULL;
LargeObjectSpace* Heap::lo_space_ = NULL;
-static const int kMinimumPromotionLimit = 2*MB;
-static const int kMinimumAllocationLimit = 8*MB;
+static const intptr_t kMinimumPromotionLimit = 2*MB;
+static const intptr_t kMinimumAllocationLimit = 8*MB;
-int Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit;
-int Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit;
+intptr_t Heap::old_gen_promotion_limit_ = kMinimumPromotionLimit;
+intptr_t Heap::old_gen_allocation_limit_ = kMinimumAllocationLimit;
int Heap::old_gen_exhausted_ = false;
@@ -83,9 +83,9 @@ int Heap::max_old_generation_size_ = 192*MB;
int Heap::initial_semispace_size_ = 128*KB;
size_t Heap::code_range_size_ = 0;
#elif defined(V8_TARGET_ARCH_X64)
-int Heap::max_semispace_size_ = 16*MB;
-int Heap::max_old_generation_size_ = 1*GB;
-int Heap::initial_semispace_size_ = 1*MB;
+intptr_t Heap::max_semispace_size_ = 16*MB;
+intptr_t Heap::max_old_generation_size_ = 1.85*GB;
+intptr_t Heap::initial_semispace_size_ = 1*MB;
size_t Heap::code_range_size_ = 512*MB;
#else
int Heap::max_semispace_size_ = 8*MB;
@@ -97,7 +97,7 @@ size_t Heap::code_range_size_ = 0;
// The snapshot semispace size will be the default semispace size if
// snapshotting is used and will be the requested semispace size as
// set up by ConfigureHeap otherwise.
-int Heap::reserved_semispace_size_ = Heap::max_semispace_size_;
+intptr_t Heap::reserved_semispace_size_ = Heap::max_semispace_size_;
List<Heap::GCPrologueCallbackPair> Heap::gc_prologue_callbacks_;
List<Heap::GCEpilogueCallbackPair> Heap::gc_epilogue_callbacks_;
@@ -645,7 +645,7 @@ void Heap::PerformGarbageCollection(AllocationSpace space,
UpdateSurvivalRateTrend(start_new_space_size);
- int old_gen_size = PromotedSpaceSize();
+ intptr_t old_gen_size = PromotedSpaceSize();
old_gen_promotion_limit_ =
old_gen_size + Max(kMinimumPromotionLimit, old_gen_size / 3);
old_gen_allocation_limit_ =
@@ -3996,7 +3996,7 @@ void Heap::RecordStats(HeapStats* stats, bool take_snapshot) {
}
-int Heap::PromotedSpaceSize() {
+intptr_t Heap::PromotedSpaceSize() {
return old_pointer_space_->Size()
+ old_data_space_->Size()
+ code_space_->Size()
diff --git a/src/heap.h b/src/heap.h
index 45fee17..d65fb31 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -243,13 +243,13 @@ class Heap : public AllStatic {
// semi space. The young generation consists of two semi spaces and
// we reserve twice the amount needed for those in order to ensure
// that new space can be aligned to its size.
- static int MaxReserved() {
+ static intptr_t MaxReserved() {
return 4 * reserved_semispace_size_ + max_old_generation_size_;
}
- static int MaxSemiSpaceSize() { return max_semispace_size_; }
- static int ReservedSemiSpaceSize() { return reserved_semispace_size_; }
- static int InitialSemiSpaceSize() { return initial_semispace_size_; }
- static int MaxOldGenerationSize() { return max_old_generation_size_; }
+ static intptr_t MaxSemiSpaceSize() { return max_semispace_size_; }
+ static intptr_t ReservedSemiSpaceSize() { return reserved_semispace_size_; }
+ static intptr_t InitialSemiSpaceSize() { return initial_semispace_size_; }
+ static intptr_t MaxOldGenerationSize() { return max_old_generation_size_; }
// Returns the capacity of the heap in bytes w/o growing. Heap grows when
// more spaces are needed until it reaches the limit.
@@ -1024,10 +1024,10 @@ class Heap : public AllStatic {
static GCTracer* tracer() { return tracer_; }
private:
- static int reserved_semispace_size_;
- static int max_semispace_size_;
- static int initial_semispace_size_;
- static int max_old_generation_size_;
+ static intptr_t reserved_semispace_size_;
+ static intptr_t max_semispace_size_;
+ static intptr_t initial_semispace_size_;
+ static intptr_t max_old_generation_size_;
static size_t code_range_size_;
// For keeping track of how much data has survived
@@ -1056,7 +1056,7 @@ class Heap : public AllStatic {
static HeapState gc_state_;
// Returns the size of object residing in non new spaces.
- static int PromotedSpaceSize();
+ static intptr_t PromotedSpaceSize();
// Returns the amount of external memory registered since last global gc.
static int PromotedExternalMemorySize();
@@ -1091,12 +1091,12 @@ class Heap : public AllStatic {
// Limit that triggers a global GC on the next (normally caused) GC. This
// is checked when we have already decided to do a GC to help determine
// which collector to invoke.
- static int old_gen_promotion_limit_;
+ static intptr_t old_gen_promotion_limit_;
// Limit that triggers a global GC as soon as is reasonable. This is
// checked before expanding a paged space in the old generation and on
// every allocation in large object space.
- static int old_gen_allocation_limit_;
+ static intptr_t old_gen_allocation_limit_;
// Limit on the amount of externally allocated memory allowed
// between global GCs. If reached a global GC is forced.
diff --git a/src/spaces.cc b/src/spaces.cc
index 67adafd..6d6bcf6 100644
--- a/src/spaces.cc
+++ b/src/spaces.cc
@@ -264,9 +264,9 @@ void CodeRange::TearDown() {
// -----------------------------------------------------------------------------
// MemoryAllocator
//
-int MemoryAllocator::capacity_ = 0;
-int MemoryAllocator::size_ = 0;
-int MemoryAllocator::size_executable_ = 0;
+intptr_t MemoryAllocator::capacity_ = 0;
+intptr_t MemoryAllocator::size_ = 0;
+intptr_t MemoryAllocator::size_executable_ = 0;
VirtualMemory* MemoryAllocator::initial_chunk_ = NULL;
@@ -295,7 +295,7 @@ int MemoryAllocator::Pop() {
void *executable_memory_histogram = NULL;
-bool MemoryAllocator::Setup(int capacity) {
+bool MemoryAllocator::Setup(intptr_t capacity) {
capacity_ = RoundUp(capacity, Page::kPageSize);
// Over-estimate the size of chunks_ array. It assumes the expansion of old
diff --git a/src/spaces.h b/src/spaces.h
index a6b8ea4..c0f76b9 100644
--- a/src/spaces.h
+++ b/src/spaces.h
@@ -489,7 +489,7 @@ class MemoryAllocator : public AllStatic {
public:
// Initializes its internal bookkeeping structures.
// Max capacity of the total space.
- static bool Setup(int max_capacity);
+ static bool Setup(intptr_t max_capacity);
// Deletes valid chunks.
static void TearDown();
@@ -636,12 +636,12 @@ class MemoryAllocator : public AllStatic {
private:
// Maximum space size in bytes.
- static int capacity_;
+ static intptr_t capacity_;
// Allocated space size in bytes.
- static int size_;
+ static intptr_t size_;
// Allocated executable space size in bytes.
- static int size_executable_;
+ static intptr_t size_executable_;
// The initial chunk of virtual memory.
static VirtualMemory* initial_chunk_;