blob: 28e5e9adf200271368248548e4c37ccc8a34b1fd [file] [edit]
/*
* Copyright (c) 2014, 2025, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "gc/shared/stringdedup/stringDedupStat.hpp"
#include "logging/log.hpp"
#include "utilities/globalDefinitions.hpp"
StringDedup::Stat::Stat() :
_inspected(0),
_known(0),
_known_shared(0),
_new(0),
_new_bytes(0),
_deduped(0),
_deduped_bytes(0),
_replaced(0),
_deleted(0),
_skipped_dead(0),
_skipped_incomplete(0),
_skipped_shared(0),
_active(0),
_idle(0),
_process(0),
_resize_table(0),
_cleanup_table(0),
_active_start(),
_active_elapsed(),
_phase_start(),
_idle_elapsed(),
_process_elapsed(),
_resize_table_elapsed(),
_cleanup_table_elapsed()
{}
void StringDedup::Stat::add(const Stat* const stat) {
_inspected += stat->_inspected;
_known += stat->_known;
_known_shared += stat->_known_shared;
_new += stat->_new;
_new_bytes += stat->_new_bytes;
_deduped += stat->_deduped;
_deduped_bytes += stat->_deduped_bytes;
_replaced += stat->_replaced;
_deleted += stat->_deleted;
_skipped_dead += stat->_skipped_dead;
_skipped_incomplete += stat->_skipped_incomplete;
_skipped_shared += stat->_skipped_shared;
_active += stat->_active;
_idle += stat->_idle;
_process += stat->_process;
_resize_table += stat->_resize_table;
_cleanup_table += stat->_cleanup_table;
_active_elapsed += stat->_active_elapsed;
_idle_elapsed += stat->_idle_elapsed;
_process_elapsed += stat->_process_elapsed;
_resize_table_elapsed += stat->_resize_table_elapsed;
_cleanup_table_elapsed += stat->_cleanup_table_elapsed;
}
// Support for log output formatting
#define STRDEDUP_PERCENT_FORMAT "%5.1f%%"
#define STRDEDUP_PERCENT_FORMAT_NS "%.1f%%"
#define STRDEDUP_BYTES_FORMAT "%8.1f%s"
#define STRDEDUP_BYTES_FORMAT_NS "%.1f%s"
#define STRDEDUP_BYTES_PARAM(bytes) byte_size_in_proper_unit((double)(bytes)), proper_unit_for_byte_size((bytes))
#define STRDEDUP_ELAPSED_FORMAT_MS "%.3fms"
static double strdedup_elapsed_param_ms(Tickspan t) {
return t.seconds() * MILLIUNITS;
}
void StringDedup::Stat::log_summary(const Stat* last_stat, const Stat* total_stat) {
double total_deduped_bytes_percent = 0.0;
if (total_stat->_new_bytes > 0) {
// Avoid division by zero
total_deduped_bytes_percent = percent_of(total_stat->_deduped_bytes, total_stat->_new_bytes);
}
log_info(stringdedup)(
"Concurrent String Deduplication "
"%zu/" STRDEDUP_BYTES_FORMAT_NS " (new), "
"%zu/" STRDEDUP_BYTES_FORMAT_NS " (deduped), "
"avg " STRDEDUP_PERCENT_FORMAT_NS ", "
STRDEDUP_ELAPSED_FORMAT_MS " of " STRDEDUP_ELAPSED_FORMAT_MS,
last_stat->_new, STRDEDUP_BYTES_PARAM(last_stat->_new_bytes),
last_stat->_deduped, STRDEDUP_BYTES_PARAM(last_stat->_deduped_bytes),
total_deduped_bytes_percent,
strdedup_elapsed_param_ms(last_stat->_process_elapsed),
strdedup_elapsed_param_ms(last_stat->_active_elapsed));
}
void StringDedup::Stat::report_active_start() {
log_debug(stringdedup, phases, start)("Active start");
_active_start = Ticks::now();
_active++;
}
void StringDedup::Stat::report_active_end() {
_active_elapsed += (Ticks::now() - _active_start);
log_debug(stringdedup, phases)("Active end: " STRDEDUP_ELAPSED_FORMAT_MS,
strdedup_elapsed_param_ms(_active_elapsed));
}
void StringDedup::Stat::report_phase_start(const char* phase) {
log_debug(stringdedup, phases, start)("%s start", phase);
_phase_start = Ticks::now();
}
void StringDedup::Stat::report_phase_end(const char* phase, Tickspan* elapsed) {
*elapsed += Ticks::now() - _phase_start;
log_debug(stringdedup, phases)("%s end: " STRDEDUP_ELAPSED_FORMAT_MS,
phase, strdedup_elapsed_param_ms(*elapsed));
}
void StringDedup::Stat::report_idle_start() {
report_phase_start("Idle");
_idle++;
}
void StringDedup::Stat::report_idle_end() {
report_phase_end("Idle", &_idle_elapsed);
}
void StringDedup::Stat::report_process_start() {
report_phase_start("Process");
_process++;
}
void StringDedup::Stat::report_process_pause() {
_process_elapsed += (Ticks::now() - _phase_start);
log_debug(stringdedup, phases)("Process paused");
}
void StringDedup::Stat::report_process_resume() {
log_debug(stringdedup, phases)("Process resume");
_phase_start = Ticks::now();
}
void StringDedup::Stat::report_process_end() {
report_phase_end("Process", &_process_elapsed);
}
void StringDedup::Stat::report_resize_table_start(size_t new_bucket_count,
size_t old_bucket_count,
size_t entry_count) {
_phase_start = Ticks::now();
++_resize_table;
log_debug(stringdedup, phases, start)
("Resize Table: %zu -> %zu (%zu)",
old_bucket_count, new_bucket_count, entry_count);
}
void StringDedup::Stat::report_resize_table_end() {
report_phase_end("Resize Table", &_resize_table_elapsed);
}
void StringDedup::Stat::report_cleanup_table_start(size_t entry_count,
size_t dead_count) {
log_debug(stringdedup, phases, start)
("Cleanup Table: %zu / %zu -> %zu",
dead_count, entry_count, (entry_count - dead_count));
_phase_start = Ticks::now();
_cleanup_table++;
}
void StringDedup::Stat::report_cleanup_table_end() {
report_phase_end("Cleanup Table", &_cleanup_table_elapsed);
}
void StringDedup::Stat::log_times(const char* prefix) const {
log_debug(stringdedup)(
" %s Process: %zu/" STRDEDUP_ELAPSED_FORMAT_MS
", Idle: %zu/" STRDEDUP_ELAPSED_FORMAT_MS,
prefix,
_process, strdedup_elapsed_param_ms(_process_elapsed),
_idle, strdedup_elapsed_param_ms(_idle_elapsed));
if (_resize_table > 0) {
log_debug(stringdedup)(
" %s Resize Table: %zu/" STRDEDUP_ELAPSED_FORMAT_MS,
prefix, _resize_table, strdedup_elapsed_param_ms(_resize_table_elapsed));
}
if (_cleanup_table > 0) {
log_debug(stringdedup)(
" %s Cleanup Table: %zu/" STRDEDUP_ELAPSED_FORMAT_MS,
prefix, _cleanup_table, strdedup_elapsed_param_ms(_cleanup_table_elapsed));
}
}
void StringDedup::Stat::log_statistics(bool total) const {
double known_percent = percent_of(_known, _inspected);
double known_shared_percent = percent_of(_known_shared, _inspected);
double new_percent = percent_of(_new, _inspected);
double deduped_percent = percent_of(_deduped, _inspected);
double deduped_bytes_percent = percent_of(_deduped_bytes, _new_bytes);
double replaced_percent = percent_of(_replaced, _new);
double deleted_percent = percent_of(_deleted, _new);
log_times(total ? "Total" : "Last");
log_debug(stringdedup)(" Inspected: %12zu", _inspected);
log_debug(stringdedup)(" Known: %12zu(%5.1f%%)", _known, known_percent);
log_debug(stringdedup)(" Shared: %12zu(%5.1f%%)", _known_shared, known_shared_percent);
log_debug(stringdedup)(" New: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT,
_new, new_percent, STRDEDUP_BYTES_PARAM(_new_bytes));
log_debug(stringdedup)(" Replaced: %12zu(%5.1f%%)", _replaced, replaced_percent);
log_debug(stringdedup)(" Deleted: %12zu(%5.1f%%)", _deleted, deleted_percent);
log_debug(stringdedup)(" Deduplicated: %12zu(%5.1f%%)" STRDEDUP_BYTES_FORMAT "(%5.1f%%)",
_deduped, deduped_percent, STRDEDUP_BYTES_PARAM(_deduped_bytes), deduped_bytes_percent);
log_debug(stringdedup)(" Skipped: %zu (dead), %zu (incomplete), %zu (shared)",
_skipped_dead, _skipped_incomplete, _skipped_shared);
}