Skip to content

Commit

Permalink
8233378: CHT: Fast reset
Browse files Browse the repository at this point in the history
Reviewed-by: tschatzl, rehn
  • Loading branch information
Ivan Walulya committed May 12, 2021
1 parent f3b510b commit dcf250d
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 3 deletions.
5 changes: 5 additions & 0 deletions src/hotspot/share/utilities/concurrentHashTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ class ConcurrentHashTable : public CHeapObj<F> {
void internal_shrink_epilog(Thread* thread);
void internal_shrink_range(Thread* thread, size_t start, size_t stop);
bool internal_shrink(Thread* thread, size_t size_limit_log2);
void internal_reset(size_t log2_size);

// Methods for growing.
bool unzip_bucket(Thread* thread, InternalTable* old_table,
Expand Down Expand Up @@ -388,6 +389,10 @@ class ConcurrentHashTable : public CHeapObj<F> {
// Re-size operations.
bool shrink(Thread* thread, size_t size_limit_log2 = 0);
bool grow(Thread* thread, size_t size_limit_log2 = 0);
// Unsafe reset and resize the table. This method assumes that we
// want to clear and maybe resize the internal table without the
// overhead of clearing individual items in the table.
void unsafe_reset(size_t size_log2 = 0);

// All callbacks for get are under critical sections. Other callbacks may be
// under critical section or may have locked parts of table. Calling any
Expand Down
22 changes: 22 additions & 0 deletions src/hotspot/share/utilities/concurrentHashTable.inline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -781,6 +781,20 @@ inline bool ConcurrentHashTable<CONFIG, F>::
return true;
}

template <typename CONFIG, MEMFLAGS F>
inline void ConcurrentHashTable<CONFIG, F>::
internal_reset(size_t log2_size)
{
assert(_table != NULL, "table failed");
assert(_log2_size_limit >= log2_size, "bad ergo");

delete _table;
// Create and publish a new table
InternalTable* table = new InternalTable(log2_size);
_size_limit_reached = (log2_size == _log2_size_limit);
Atomic::release_store(&_table, table);
}

template <typename CONFIG, MEMFLAGS F>
inline bool ConcurrentHashTable<CONFIG, F>::
internal_grow_prolog(Thread* thread, size_t log2_size)
Expand Down Expand Up @@ -1032,6 +1046,14 @@ inline bool ConcurrentHashTable<CONFIG, F>::
return ret;
}

template <typename CONFIG, MEMFLAGS F>
inline void ConcurrentHashTable<CONFIG, F>::
unsafe_reset(size_t size_log2)
{
size_t tmp = size_log2 == 0 ? _log2_start_size : size_log2;
internal_reset(tmp);
}

template <typename CONFIG, MEMFLAGS F>
inline bool ConcurrentHashTable<CONFIG, F>::
grow(Thread* thread, size_t size_limit_log2)
Expand Down
77 changes: 74 additions & 3 deletions test/hotspot/gtest/utilities/test_concurrentHashtable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,46 @@ struct Pointer : public AllStatic {
}
};

struct Config : public AllStatic {
typedef uintptr_t Value;
struct TableElement{
TableElement * volatile _next;
Value _value;
};

static const uint nelements = 5;
static TableElement* elements;
static uint cur_index;

static uintx get_hash(const Value& value, bool* dead_hash) {
return (uintx)value;
}
static void initialize() {
elements = (TableElement*)::malloc(nelements * sizeof(TableElement));
}
static void* allocate_node(size_t size, const Value& value) {
return (void*)&elements[cur_index++];
}

static void free_node(void* memory, const Value& value) {
return;
}

static void reset() {
cur_index = 0;
}

static void bulk_free() {
::free(elements);
}
};

Config::TableElement* Config::elements = nullptr;
uint Config::cur_index = 0;

typedef ConcurrentHashTable<Pointer, mtInternal> SimpleTestTable;
typedef ConcurrentHashTable<Pointer, mtInternal>::MultiGetHandle SimpleTestGetHandle;
typedef ConcurrentHashTable<Config, mtInternal> CustomTestTable;

struct SimpleTestLookup {
uintptr_t _val;
Expand All @@ -75,20 +113,23 @@ struct ValueGet {
}
};

static uintptr_t cht_get_copy(SimpleTestTable* cht, Thread* thr, SimpleTestLookup stl) {
template <typename T=SimpleTestTable>
static uintptr_t cht_get_copy(T* cht, Thread* thr, SimpleTestLookup stl) {
ValueGet vg;
cht->get(thr, stl, vg);
return vg.get_value();
}

static void cht_find(Thread* thr, SimpleTestTable* cht, uintptr_t val) {
template <typename T=SimpleTestTable>
static void cht_find(Thread* thr, T* cht, uintptr_t val) {
SimpleTestLookup stl(val);
ValueGet vg;
EXPECT_EQ(cht->get(thr, stl, vg), true) << "Getting an old value failed.";
EXPECT_EQ(val, vg.get_value()) << "Getting an old value failed.";
}

static void cht_insert_and_find(Thread* thr, SimpleTestTable* cht, uintptr_t val) {
template <typename T=SimpleTestTable>
static void cht_insert_and_find(Thread* thr, T* cht, uintptr_t val) {
SimpleTestLookup stl(val);
EXPECT_EQ(cht->insert(thr, stl, val), true) << "Inserting an unique value failed.";
cht_find(thr, cht, val);
Expand Down Expand Up @@ -220,6 +261,32 @@ static void cht_getinsert_bulkdelete_task(Thread* thr) {
delete cht;
}

static void cht_reset_shrink(Thread* thr) {
uintptr_t val1 = 1;
uintptr_t val2 = 2;
uintptr_t val3 = 3;
SimpleTestLookup stl1(val1), stl2(val2), stl3(val3);

Config::initialize();
CustomTestTable* cht = new CustomTestTable();

cht_insert_and_find(thr, cht, val1);
cht_insert_and_find(thr, cht, val2);
cht_insert_and_find(thr, cht, val3);

cht->unsafe_reset();
Config::reset();

EXPECT_EQ(cht_get_copy(cht, thr, stl1), (uintptr_t)0) << "Table should have been reset";
// Re-inserted values should not be considered duplicates; table was reset.
cht_insert_and_find(thr, cht, val1);
cht_insert_and_find(thr, cht, val2);
cht_insert_and_find(thr, cht, val3);

delete cht;
Config::bulk_free();
}

static void cht_scope(Thread* thr) {
uintptr_t val = 0x2;
SimpleTestLookup stl(val);
Expand Down Expand Up @@ -394,6 +461,10 @@ TEST_VM(ConcurrentHashTable, basic_get_insert_bulk_delete_task) {
nomt_test_doer(cht_getinsert_bulkdelete_task);
}

TEST_VM(ConcurrentHashTable, basic_reset_shrink) {
nomt_test_doer(cht_reset_shrink);
}

TEST_VM(ConcurrentHashTable, basic_scan) {
nomt_test_doer(cht_scan);
}
Expand Down

1 comment on commit dcf250d

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.