| /* |
| * 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); |
| } |