Commit 610c0d75 authored by heimbuef's avatar heimbuef Committed by Commit bot

New zone-backed list datastructure to replace ZoneList

Since ZoneLists are essentially non-standard ZoneVectors and have a bad
growing behaviour (ZoneList-allocations make up ~50% of website parse
zone memory) we should stop using them. The zone-containers are merely
a clean-up, with none of them actually better suited to be used with
zones. This new datastructure allows most operations of a LinkedList (
except pop_first and insertAt/removeAt) but uses about the same memory
as a well-initialized ZoneVector/ZoneList (<3% overhead with reasonably
large lists). It also never attempts to free memory again (which would
not work in zones anyway).

The ZoneChunkList is essentially a doubly-linked-list of arrays of
variable size.

Some test-results where I tried storing 16k pointers in different list
types (lists themselves also zone-allocated):

List type                       Zone memory used   Time taken
-----------------------------------------------------------------------
Zone array (for comparison)     131072 B

Ideally initialized ZoneList    131088 B           0.062ms

ChunkZoneList                   134744 B           0.052ms <--new thing

ZoneDeque                       141744 B

ZoneLinkedList                  393264 B

Initially empty ZoneList        524168 B           0.171ms <--right now

ChunkZoneList only push_front   524320 B

Review-Url: https://codereview.chromium.org/2449383002
Cr-Commit-Position: refs/heads/master@{#40602}
parent 24d38be1
......@@ -1737,6 +1737,7 @@ v8_source_set("v8_base") {
"src/zone/accounting-allocator.h",
"src/zone/zone-allocator.h",
"src/zone/zone-allocator.h",
"src/zone/zone-chunk-list.h",
"src/zone/zone-containers.h",
"src/zone/zone-segment.cc",
"src/zone/zone-segment.h",
......
......@@ -1279,6 +1279,7 @@
'zone/zone-segment.h',
'zone/zone.cc',
'zone/zone.h',
'zone/zone-chunk-list.h',
'zone/zone-segment.cc',
'zone/zone-segment.h',
'zone/zone-allocator.h',
......
This diff is collapsed.
......@@ -131,6 +131,7 @@ v8_executable("unittests") {
"wasm/wasm-macro-gen-unittest.cc",
"wasm/wasm-module-builder-unittest.cc",
"zone/segmentpool-unittest.cc",
"zone/zone-chunk-list-unittest.cc",
]
if (v8_current_cpu == "arm") {
......
......@@ -119,6 +119,7 @@
'test-utils.cc',
'value-serializer-unittest.cc',
'zone/segmentpool-unittest.cc',
'zone/zone-chunk-list-unittest.cc',
'wasm/asm-types-unittest.cc',
'wasm/ast-decoder-unittest.cc',
'wasm/control-transfer-unittest.cc',
......
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/zone/zone-chunk-list.h"
#include "src/list-inl.h"
#include "src/zone/accounting-allocator.h"
#include "src/zone/zone.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
const size_t kItemCount = size_t(1) << 10;
TEST(ZoneChunkList, ForwardIterationTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
size_t count = 0;
for (uintptr_t item : zone_chunk_list) {
EXPECT_EQ(static_cast<size_t>(item), count);
count++;
}
EXPECT_EQ(count, kItemCount);
}
TEST(ZoneChunkList, ReverseIterationTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
size_t count = 0;
for (auto it = zone_chunk_list.rbegin(); it != zone_chunk_list.rend(); ++it) {
EXPECT_EQ(static_cast<size_t>(*it), kItemCount - count - 1);
count++;
}
EXPECT_EQ(count, kItemCount);
}
TEST(ZoneChunkList, PushFrontTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_front(static_cast<uintptr_t>(i));
}
size_t count = 0;
for (uintptr_t item : zone_chunk_list) {
EXPECT_EQ(static_cast<size_t>(item), kItemCount - count - 1);
count++;
}
EXPECT_EQ(count, kItemCount);
}
TEST(ZoneChunkList, RewindTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
zone_chunk_list.Rewind(42);
size_t count = 0;
for (uintptr_t item : zone_chunk_list) {
EXPECT_EQ(static_cast<size_t>(item), count);
count++;
}
EXPECT_EQ(count, 42);
EXPECT_EQ(count, zone_chunk_list.size());
zone_chunk_list.Rewind(0);
count = 0;
for (uintptr_t item : zone_chunk_list) {
USE(item);
count++;
}
EXPECT_EQ(count, 0);
EXPECT_EQ(count, zone_chunk_list.size());
zone_chunk_list.Rewind(100);
count = 0;
for (uintptr_t item : zone_chunk_list) {
EXPECT_EQ(static_cast<size_t>(item), count);
count++;
}
EXPECT_EQ(count, 0);
EXPECT_EQ(count, zone_chunk_list.size());
}
TEST(ZoneChunkList, FindTest) {
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
ZoneChunkList<uintptr_t> zone_chunk_list(&zone);
for (size_t i = 0; i < kItemCount; ++i) {
zone_chunk_list.push_back(static_cast<uintptr_t>(i));
}
const size_t index = kItemCount / 2 + 42;
EXPECT_EQ(*zone_chunk_list.Find(index), static_cast<uintptr_t>(index));
*zone_chunk_list.Find(index) = 42;
EXPECT_EQ(*zone_chunk_list.Find(index), 42);
}
} // namespace internal
} // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment