mariadb/storage/innobase/include/mariadb_stats.h
Sergei Petrunia 513c827041 MDEV-34190: r_engine_stats.pages_read_count is unrealistically low
The symptoms were: take a server with no activity and a table that's
not in the buffer pool. Run a query that reads the whole table and
observe that r_engine_stats.pages_read_count shows about 2% of the table
was read. Who reads the rest?

The cause was that page prefetching done inside InnoDB was not counted.

This counts page prefetch requests made in buf_read_ahead_random() and
buf_read_ahead_linear() and makes them visible in:

- ANALYZE: r_engine_stats.pages_prefetch_read_count
- Slow Query Log: Pages_prefetched:

This patch intentionally doesn't attempt to count the time to read the
prefetched pages:
* there's no obvious place where one can do it
* prefetch reads may be done in parallel (right?), it is not clear how
  to count the time in this case.
2024-07-04 15:24:49 +03:00

135 lines
3.3 KiB
C++

/*****************************************************************************
Copyright (c) 2023, MariaDB Foundation
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program 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 for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
*****************************************************************************/
#pragma once
#include "ha_handler_stats.h"
#include "my_rdtsc.h"
/* We do not want a dynamic initialization function to be
conditionally invoked on each access to a C++11 extern thread_local. */
#if __cplusplus >= 202002L
# define simple_thread_local constinit thread_local
#else
# define simple_thread_local IF_WIN(__declspec(thread),__thread)
#endif
/** Pointer to handler::active_handler_stats or nullptr (via .tbss) */
extern simple_thread_local ha_handler_stats *mariadb_stats;
/*
Returns nonzero if MariaDB wants engine status
*/
inline uint mariadb_stats_active()
{
if (ha_handler_stats *stats= mariadb_stats)
return stats->active;
return 0;
}
/* The following functions increment different engine status */
inline void mariadb_increment_pages_accessed(ha_handler_stats *stats)
{
if (stats)
stats->pages_accessed++;
}
inline void mariadb_increment_pages_accessed()
{
mariadb_increment_pages_accessed(mariadb_stats);
}
inline void mariadb_increment_pages_updated(ulonglong count)
{
if (ha_handler_stats *stats= mariadb_stats)
stats->pages_updated+= count;
}
inline void mariadb_increment_pages_read(ha_handler_stats *stats)
{
if (stats)
stats->pages_read_count++;
}
inline void mariadb_increment_pages_read()
{
mariadb_increment_pages_read(mariadb_stats);
}
inline void mariadb_increment_undo_records_read()
{
if (ha_handler_stats *stats= mariadb_stats)
stats->undo_records_read++;
}
inline void mariadb_increment_pages_prefetched(ulint n_pages)
{
if (ha_handler_stats *stats= mariadb_stats)
stats->pages_prefetched += n_pages;
}
/*
The following has to be identical code as measure() in sql_analyze_stmt.h
One should only call this if mariadb_stats_active() is true.
*/
inline ulonglong mariadb_measure()
{
#if (MY_TIMER_ROUTINE_CYCLES)
return my_timer_cycles();
#else
return my_timer_microseconds();
#endif
}
/*
Call this only of start_time != 0
See buf0rea.cc for an example of how to use it efficiently
*/
inline void mariadb_increment_pages_read_time(ulonglong start_time)
{
ha_handler_stats *stats= mariadb_stats;
ulonglong end_time= mariadb_measure();
/* Check that we only call this if active, see example! */
DBUG_ASSERT(start_time);
DBUG_ASSERT(stats->active);
stats->pages_read_time+= (end_time - start_time);
}
/*
Helper class to set mariadb_stats temporarly for one call in handler.cc
*/
class mariadb_set_stats
{
public:
mariadb_set_stats(ha_handler_stats *stats)
{
mariadb_stats= stats;
}
~mariadb_set_stats()
{
mariadb_stats= nullptr;
}
};