8291970: Add TableStatistics get function to ResourceHashtable

Reviewed-by: iklam, ccheung
This commit is contained in:
Coleen Phillimore 2022-08-09 11:59:02 +00:00
parent cbc9040f3a
commit f5b3618c42
4 changed files with 74 additions and 3 deletions

View File

@ -26,6 +26,8 @@
#define SHARE_UTILITIES_RESOURCEHASH_HPP
#include "memory/allocation.hpp"
#include "utilities/numberSeq.hpp"
#include "utilities/tableStatistics.hpp"
template<typename K, typename V>
class ResourceHashtableNode : public ResourceObj {
@ -259,6 +261,26 @@ class ResourceHashtableBase : public STORAGE {
}
}
template<typename Function>
TableStatistics statistics_calculate(Function size_function) const {
NumberSeq summary;
size_t literal_bytes = 0;
Node* const* bucket = table();
const unsigned sz = table_size();
while (bucket < bucket_at(sz)) {
Node* node = *bucket;
int count = 0;
while (node != NULL) {
literal_bytes += size_function(node->_key, node->_value);
count++;
node = node->_next;
}
summary.add((double)count);
++bucket;
}
return TableStatistics(summary, literal_bytes, sizeof(Node*), sizeof(Node));
}
};
template<unsigned TABLE_SIZE, typename K, typename V>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -91,7 +91,7 @@ TableStatistics::TableStatistics() :
_add_rate(0), _remove_rate(0) {
}
TableStatistics::TableStatistics(TableRateStatistics& rate_stats, NumberSeq summary, size_t literal_bytes, size_t bucket_bytes, size_t node_bytes) :
TableStatistics::TableStatistics(NumberSeq summary, size_t literal_bytes, size_t bucket_bytes, size_t node_bytes) :
_literal_bytes(literal_bytes),
_number_of_buckets(0), _number_of_entries(0),
_maximum_bucket_size(0), _average_bucket_size(0),
@ -114,7 +114,12 @@ TableStatistics::TableStatistics(TableRateStatistics& rate_stats, NumberSeq summ
_bucket_size = (_number_of_buckets <= 0) ? 0 : (_bucket_bytes / _number_of_buckets);
_entry_size = (_number_of_entries <= 0) ? 0 : (_entry_bytes / _number_of_entries);
}
TableStatistics::TableStatistics(TableRateStatistics& rate_stats,
NumberSeq summary, size_t literal_bytes,
size_t bucket_bytes, size_t node_bytes) :
TableStatistics(summary, literal_bytes, bucket_bytes, node_bytes) {
#if INCLUDE_JFR
if (Jfr::is_recording()) {
rate_stats.stamp();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -82,6 +82,7 @@ public:
float _remove_rate;
TableStatistics();
TableStatistics(NumberSeq summary, size_t literal_bytes, size_t bucket_bytes, size_t node_bytes);
TableStatistics(TableRateStatistics& rate_stats, NumberSeq summary, size_t literal_bytes, size_t bucket_bytes, size_t node_bytes);
~TableStatistics();

View File

@ -446,3 +446,46 @@ TEST_VM_F(ResourceHashtableDeleteTest, check_delete_ptr) {
// Removal should make the refcount be the original refcount.
ASSERT_EQ(s->refcount(), s_orig_count) << "refcount should be as we started";
}
class ResourceHashtablePrintTest : public ::testing::Test {
public:
class TestValue {
int _i;
int _j;
int _k;
public:
TestValue(int i) : _i(i), _j(i+1), _k(i+2) {}
};
ResourceHashtable<int, TestValue*, 30, ResourceObj::C_HEAP, mtTest> _test_table;
class TableDeleter {
public:
bool do_entry(int& key, TestValue*& val) {
delete val;
return true;
}
};
};
TEST_VM_F(ResourceHashtablePrintTest, print_test) {
for (int i = 0; i < 300; i++) {
TestValue* tv = new TestValue(i);
_test_table.put(i, tv); // all the entries can be the same.
}
auto printer = [&] (int& key, TestValue*& val) {
return sizeof(*val);
};
TableStatistics ts = _test_table.statistics_calculate(printer);
ResourceMark rm;
stringStream st;
ts.print(&st, "TestTable");
// Verify output in string
const char* strings[] = {
"Number of buckets", "Number of entries", "300", "Number of literals", "Average bucket size", "Maximum bucket size" };
for (const auto& str : strings) {
ASSERT_TRUE(strstr(st.as_string(), str) != nullptr) << "string not present " << str;
}
// Cleanup: need to delete pointers in entries
TableDeleter deleter;
_test_table.unlink(&deleter);
}