Skip to content

Commit 3961c95

Browse files
committed
i#7731:Optimize reuse distance using splay tree
Improve reuse distance using splay tree instead of linked list. Splay tree have asymptotic O(log n) amortizated time for all operations instead of O(n / const) for linked list with skip list. Perfomance improve achives in avarage 10-40% based on different benchmarks . Fixes #7731
1 parent 2e3c900 commit 3961c95

File tree

2 files changed

+339
-209
lines changed

2 files changed

+339
-209
lines changed

clients/drcachesim/tools/reuse_distance.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,8 @@ reuse_distance_t::shard_data_t::shard_data_t(uint64_t reuse_threshold, uint64_t
103103
uint32_t distance_limit, bool verify)
104104
: distance_limit(distance_limit)
105105
{
106-
ref_list = std::unique_ptr<line_ref_list_t>(
107-
new line_ref_list_t(reuse_threshold, skip_dist, verify));
106+
ref_list = std::unique_ptr<line_ref_splay_t>(
107+
new line_ref_splay_t(reuse_threshold, skip_dist, verify));
108108
}
109109

110110
bool
@@ -166,12 +166,12 @@ reuse_distance_t::parallel_shard_memref(void *shard_data, const memref_t &memref
166166
++shard->data_refs;
167167
}
168168
addr_t tag = memref.data.addr >> line_size_bits_;
169-
std::unordered_map<addr_t, line_ref_t *>::iterator it =
169+
std::unordered_map<addr_t, line_ref_node_t *>::iterator it =
170170
shard->cache_map.find(tag);
171171
if (it == shard->cache_map.end()) {
172-
line_ref_t *ref = new line_ref_t(tag);
172+
line_ref_node_t *ref = new line_ref_node_t(tag);
173173
// insert into the map
174-
shard->cache_map.insert(std::pair<addr_t, line_ref_t *>(tag, ref));
174+
shard->cache_map.insert(std::pair<addr_t, line_ref_node_t *>(tag, ref));
175175
// insert into the list
176176
shard->ref_list->add_to_front(ref);
177177
// See if the line we're adding was previously removed.
@@ -237,8 +237,8 @@ cmp_dist_key(const reuse_distance_t::distance_map_pair_t &l,
237237
}
238238

239239
static bool
240-
cmp_total_refs(const std::pair<addr_t, line_ref_t *> &l,
241-
const std::pair<addr_t, line_ref_t *> &r)
240+
cmp_total_refs(const std::pair<addr_t, line_ref_node_t *> &l,
241+
const std::pair<addr_t, line_ref_node_t *> &r)
242242
{
243243
if (l.second->total_refs > r.second->total_refs)
244244
return true;
@@ -252,8 +252,8 @@ cmp_total_refs(const std::pair<addr_t, line_ref_t *> &l,
252252
}
253253

254254
static bool
255-
cmp_distant_refs(const std::pair<addr_t, line_ref_t *> &l,
256-
const std::pair<addr_t, line_ref_t *> &r)
255+
cmp_distant_refs(const std::pair<addr_t, line_ref_node_t *> &l,
256+
const std::pair<addr_t, line_ref_node_t *> &r)
257257
{
258258
if (l.second->distant_refs > r.second->distant_refs)
259259
return true;
@@ -324,15 +324,15 @@ reuse_distance_t::print_shard_results(const shard_data_t *shard)
324324
std::cerr << "\n";
325325
std::cerr << "Reuse distance threshold = " << knobs_.distance_threshold
326326
<< " cache lines\n";
327-
std::vector<std::pair<addr_t, line_ref_t *>> top(knobs_.report_top);
327+
std::vector<std::pair<addr_t, line_ref_node_t *>> top(knobs_.report_top);
328328
std::partial_sort_copy(shard->cache_map.begin(), shard->cache_map.end(), top.begin(),
329329
top.end(), cmp_total_refs);
330330
std::cerr << "Top " << top.size() << " frequently referenced cache lines\n";
331331
std::cerr << std::setw(18) << "cache line"
332332
<< ": " << std::setw(17) << "#references " << std::setw(14)
333333
<< "#distant refs"
334334
<< "\n";
335-
for (std::vector<std::pair<addr_t, line_ref_t *>>::iterator it = top.begin();
335+
for (std::vector<std::pair<addr_t, line_ref_node_t *>>::iterator it = top.begin();
336336
it != top.end(); ++it) {
337337
if (it->second == NULL) // Very small app.
338338
break;
@@ -350,7 +350,7 @@ reuse_distance_t::print_shard_results(const shard_data_t *shard)
350350
<< ": " << std::setw(17) << "#references " << std::setw(14)
351351
<< "#distant refs"
352352
<< "\n";
353-
for (std::vector<std::pair<addr_t, line_ref_t *>>::iterator it = top.begin();
353+
for (std::vector<std::pair<addr_t, line_ref_node_t *>>::iterator it = top.begin();
354354
it != top.end(); ++it) {
355355
if (it->second == NULL) // Very small app.
356356
break;
@@ -484,11 +484,11 @@ reuse_distance_t::get_aggregated_results()
484484
}
485485
for (const auto &entry : shard.second->cache_map) {
486486
const auto &existing = aggregated_results_->cache_map.find(entry.first);
487-
line_ref_t *ref;
487+
line_ref_node_t *ref;
488488
if (existing == aggregated_results_->cache_map.end()) {
489-
ref = new line_ref_t(entry.first);
489+
ref = new line_ref_node_t(entry.first);
490490
aggregated_results_->cache_map.insert(
491-
std::pair<addr_t, line_ref_t *>(entry.first, ref));
491+
std::pair<addr_t, line_ref_node_t *>(entry.first, ref));
492492
ref->total_refs = 0;
493493
} else {
494494
ref = existing->second;
@@ -507,7 +507,7 @@ reuse_distance_t::print_results()
507507
std::cerr << TOOL_NAME << " aggregated results:\n";
508508
print_shard_results(get_aggregated_results());
509509

510-
// For regular shards the line_ref_t's are deleted in ~line_ref_list_t.
510+
// For regular shards the line_ref_node_t's are deleted in ~line_ref_splay_t.
511511
for (auto &iter : get_aggregated_results()->cache_map) {
512512
delete iter.second;
513513
}

0 commit comments

Comments
 (0)