MySQL 9.1.0
Source Code Documentation
timing_iterator.h
Go to the documentation of this file.
1#ifndef SQL_ITERATORS_TIMING_ITERATOR_H_
2#define SQL_ITERATORS_TIMING_ITERATOR_H_
3
4/* Copyright (c) 2019, 2024, Oracle and/or its affiliates.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9
10 This program is designed to work with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation. The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have either included with
16 the program or referenced in the documentation.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License, version 2.0, for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
26
27#include <inttypes.h>
28#include <stdio.h>
29#include <chrono>
30
31#include "my_alloc.h"
33#include "sql/sql_class.h"
34#include "sql/sql_lex.h"
35
36/**
37 This class is used in implementing the 'EXPLAIN ANALYZE' command.
38 It maintains a set of profiling data.
39*/
41 public:
42 // To avoid a lot of repetitive writing.
43 using steady_clock = std::chrono::steady_clock;
44 using duration = steady_clock::time_point::duration;
45 using TimeStamp = steady_clock::time_point;
46
47 /** Return current time.*/
48 static TimeStamp Now() {
49#if defined(__linux__)
50 // Work around very slow libstdc++ implementations of std::chrono
51 // (those compiled with _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL).
52 timespec tp;
53 clock_gettime(CLOCK_MONOTONIC, &tp);
54 return steady_clock::time_point(
55 steady_clock::duration(std::chrono::seconds(tp.tv_sec) +
56 std::chrono::nanoseconds(tp.tv_nsec)));
57#else
58 return steady_clock::now();
59#endif
60 }
61
62 double GetFirstRowMs() const override {
64 }
65 double GetLastRowMs() const override {
67 }
68
69 uint64_t GetNumInitCalls() const override { return m_num_init_calls; }
70 uint64_t GetNumRows() const override { return m_num_rows; }
71
72 /** Mark the end of an iterator->Init() call.*/
73 void StopInit(TimeStamp start_time) {
74 m_elapsed_first_row += Now() - start_time;
76 m_first_row = true;
77 }
78
79 /**
80 Update the number of rows read. Note that this function is only called
81 for iterator where we read all rows during iterator->Init()
82 (@see MaterializeIterator and @see TemptableAggregateIterator).
83 */
84 void IncrementNumRows(uint64_t materialized_rows) {
85 m_num_rows += materialized_rows;
86 }
87
88 /**
89 Mark the end of an iterator->Read() call.
90 @param start_time time when Read() started.
91 @param read_ok 'true' if Read() was successful.
92 */
93 void StopRead(TimeStamp start_time, bool read_ok) {
94 if (m_first_row) {
95 m_elapsed_first_row += Now() - start_time;
96 m_first_row = false;
97 } else {
98 m_elapsed_other_rows += Now() - start_time;
99 }
100 if (read_ok) {
101 m_num_rows++;
102 }
103 }
104
105 private:
106 static double DurationToMs(duration dur) {
107 return std::chrono::duration<double>(dur).count() * 1e3;
108 }
109
110 /** The number of loops.*/
111 uint64_t m_num_init_calls{0};
112
113 /** The number of rows fetched. (Sum for all loops.)*/
114 uint64_t m_num_rows{0};
115
116 /** True if we are about to read the first row.*/
118
119 /**
120 Elapsed time in all calls to m_iterator.Init() and Read() for the
121 first row.
122 */
124
125 /**
126 Elapsed time in all calls to m_iterator.Read() for all but the first
127 row.
128 */
130};
131
132/**
133 An iterator template that wraps a RowIterator, such that all calls to Init()
134 and Read() are timed (all others are passed through unchanged, and possibly
135 even inlined, since all RowIterator implementations are final). This is used
136 for EXPLAIN ANALYZE.
137
138 Note that MaterializeIterator does not use this class. Doing so
139 would give misleading measurements. MaterializeIterator has an
140 internal member iterator (m_table_iterator) that iterates over the
141 materialized result. Calls to Init()/Read() on that iterator goes
142 via Init()/Read() on the MaterializeIterator. And the internal
143 iterator is listed above MaterializeIterator in 'EXPLAIN ANALYZE'
144 output. Its elapsed time values should thus include both the cost of
145 materialization and iterating over the result, while the entry for
146 MaterializeIterator should only show the time spent on
147 materialization. But if we used TimingIterator, the entry for
148 MaterializeIterator would give the sum of time spent on both
149 materialization and iteration, and the entry for the internal
150 iterator would only show the time spent on iterating over the
151 materialized result. (See also Bug #33834146 "'EXPLAIN ANALYZE' cost
152 estimates and elapsed time values are not cumulative"). This also
153 applies to TemptableAggregateIterator. These classes therefore have
154 other mechanisms for obtaining profiling data.
155
156 See also NewIterator, below.
157 */
158template <class RealIterator>
159class TimingIterator final : public RowIterator {
160 public:
161 template <class... Args>
162 TimingIterator(THD *thd, Args &&...args)
163 : RowIterator(thd), m_iterator(thd, std::forward<Args>(args)...) {}
164
165 bool Init() override {
166 const IteratorProfilerImpl::TimeStamp start_time =
168 bool err = m_iterator.Init();
169 m_profiler.StopInit(start_time);
170 return err;
171 }
172
173 int Read() override {
174 const IteratorProfilerImpl::TimeStamp start_time =
176 int err = m_iterator.Read();
177 m_profiler.StopRead(start_time, err == 0);
178 return err;
179 }
180
181 void SetNullRowFlag(bool is_null_row) override {
182 m_iterator.SetNullRowFlag(is_null_row);
183 }
184 void UnlockRow() override { m_iterator.UnlockRow(); }
185 void StartPSIBatchMode() override { m_iterator.StartPSIBatchMode(); }
186 void EndPSIBatchModeIfStarted() override {
187 m_iterator.EndPSIBatchModeIfStarted();
188 }
189
190 void SetOverrideProfiler(const IteratorProfiler *profiler) override {
191 m_override_profiler = profiler;
192 }
193
194 const IteratorProfiler *GetProfiler() const override {
196 }
197
198 RealIterator *real_iterator() override { return &m_iterator; }
199 const RealIterator *real_iterator() const override { return &m_iterator; }
200
201 private:
202 /** This maintains the profiling measurements.*/
204
205 /**
206 For iterators over materialized tables we must make profiling
207 measurements in a different way. This field keeps those measurements.
208 */
210
211 RealIterator m_iterator;
212};
213
214// Allocates a new iterator on the given MEM_ROOT. The MEM_ROOT must live
215// for at least as long as the iterator does.
216//
217// If we are in EXPLAIN ANALYZE, the iterator is wrapped in a TimingIterator<T>,
218// so that it collects timing information. For this reason, nearly all
219// instantiations of iterators should go through this function.
220
221template <class RealIterator, class... Args>
223 Args &&...args) {
224 if (thd->lex->is_explain_analyze) {
226 new (mem_root)
227 TimingIterator<RealIterator>(thd, std::forward<Args>(args)...));
228 } else {
230 new (mem_root) RealIterator(thd, std::forward<Args>(args)...));
231 }
232}
233
234#endif // SQL_ITERATORS_TIMING_ITERATOR_H_
This class is used in implementing the 'EXPLAIN ANALYZE' command.
Definition: timing_iterator.h:40
uint64_t GetNumRows() const override
The number of rows fetched.
Definition: timing_iterator.h:70
static double DurationToMs(duration dur)
Definition: timing_iterator.h:106
std::chrono::steady_clock steady_clock
Definition: timing_iterator.h:43
uint64_t GetNumInitCalls() const override
The number of loops (i.e number of iterator->Init() calls.
Definition: timing_iterator.h:69
steady_clock::time_point TimeStamp
Definition: timing_iterator.h:45
void IncrementNumRows(uint64_t materialized_rows)
Update the number of rows read.
Definition: timing_iterator.h:84
duration m_elapsed_other_rows
Elapsed time in all calls to m_iterator.Read() for all but the first row.
Definition: timing_iterator.h:129
bool m_first_row
True if we are about to read the first row.
Definition: timing_iterator.h:117
steady_clock::time_point::duration duration
Definition: timing_iterator.h:44
void StopInit(TimeStamp start_time)
Mark the end of an iterator->Init() call.
Definition: timing_iterator.h:73
uint64_t m_num_init_calls
The number of loops.
Definition: timing_iterator.h:111
static TimeStamp Now()
Return current time.
Definition: timing_iterator.h:48
double GetFirstRowMs() const override
Time (in ms) spent fetching the first row.
Definition: timing_iterator.h:62
double GetLastRowMs() const override
Time (in ms) spent fetching the remaining rows.
Definition: timing_iterator.h:65
uint64_t m_num_rows
The number of rows fetched.
Definition: timing_iterator.h:114
duration m_elapsed_first_row
Elapsed time in all calls to m_iterator.Init() and Read() for the first row.
Definition: timing_iterator.h:123
void StopRead(TimeStamp start_time, bool read_ok)
Mark the end of an iterator->Read() call.
Definition: timing_iterator.h:93
Profiling data for an iterator, needed by 'EXPLAIN ANALYZE'.
Definition: row_iterator.h:41
A context for reading through a single table using a chosen access method: index read,...
Definition: row_iterator.h:82
THD * thd() const
Definition: row_iterator.h:228
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:36
LEX * lex
Definition: sql_class.h:1001
An iterator template that wraps a RowIterator, such that all calls to Init() and Read() are timed (al...
Definition: timing_iterator.h:159
TimingIterator(THD *thd, Args &&...args)
Definition: timing_iterator.h:162
void SetOverrideProfiler(const IteratorProfiler *profiler) override
Definition: timing_iterator.h:190
RealIterator m_iterator
Definition: timing_iterator.h:211
int Read() override
Read a single row.
Definition: timing_iterator.h:173
RealIterator * real_iterator() override
If this iterator is wrapping a different iterator (e.g.
Definition: timing_iterator.h:198
bool Init() override
Initialize or reinitialize the iterator.
Definition: timing_iterator.h:165
IteratorProfilerImpl m_profiler
This maintains the profiling measurements.
Definition: timing_iterator.h:203
void EndPSIBatchModeIfStarted() override
Ends performance schema batch mode, if started.
Definition: timing_iterator.h:186
void StartPSIBatchMode() override
Start performance schema batch mode, if supported (otherwise ignored).
Definition: timing_iterator.h:185
const IteratorProfiler * GetProfiler() const override
Get profiling data for this iterator (for 'EXPLAIN ANALYZE').
Definition: timing_iterator.h:194
void UnlockRow() override
Definition: timing_iterator.h:184
const IteratorProfiler * m_override_profiler
For iterators over materialized tables we must make profiling measurements in a different way.
Definition: timing_iterator.h:209
const RealIterator * real_iterator() const override
Definition: timing_iterator.h:199
void SetNullRowFlag(bool is_null_row) override
Mark the current row buffer as containing a NULL row or not, so that if you read from it and the flag...
Definition: timing_iterator.h:181
static MEM_ROOT mem_root
Definition: client_plugin.cc:114
This file follows Google coding style, except for the name MEM_ROOT (which is kept for historical rea...
std::unique_ptr< T, Destroy_only< T > > unique_ptr_destroy_only
std::unique_ptr, but only destroying.
Definition: my_alloc.h:480
static Value err()
Create a Value object that represents an error condition.
Definition: json_binary.cc:908
Definition: gcs_xcom_synode.h:64
bool is_explain_analyze
Definition: sql_lex.h:3892
The MEM_ROOT is a simple arena, where allocations are carved out of larger blocks.
Definition: my_alloc.h:83
double seconds()
Definition: task.cc:310
unique_ptr_destroy_only< RowIterator > NewIterator(THD *thd, MEM_ROOT *mem_root, Args &&...args)
Definition: timing_iterator.h:222