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