MySQL 8.4.0
Source Code Documentation
optimizer_trace.h
Go to the documentation of this file.
1/* Copyright (c) 2023, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef SQL_JOIN_OPTIMIZER_OPTIMIZER_TRACE_H_
25#define SQL_JOIN_OPTIMIZER_OPTIMIZER_TRACE_ 1
26
27#include <array>
28#include <cassert>
29#include <deque>
30#include <ostream>
31
33#include "sql/sql_lex.h"
34
35/**
36 This class is used for storing unstructured optimizer trace text
37 (as used by the Hypergraph optimizer). It is used as the
38 std::streambuf object of an associated std::ostream (which writes
39 the formatted text into a TraceBuffer object).
40 The text is stored in a non-consecutive sequence of segments, where
41 each segment has a chunk of consecutive memory. That way, the
42 buffer can grow without having to copy the text into ever bigger
43 buffers of consecutive memory.
44*/
45class TraceBuffer final : public std::streambuf {
46 public:
47 /// The size of each consecutive buffer.
48 static constexpr size_t kSegmentSize = 4096;
49
50 private:
51 /// A consecutive buffer.
52 using Segment = std::array<char, kSegmentSize>;
53 /// The sequence of consecutive buffers.
54 using DequeType = std::deque<Segment>;
55
56 public:
57 /**
58 Called by std::ostream if the current segment is full.
59 Allocate a new segment and put 'ch' at the beginning of it.
60 */
61 int_type overflow(int_type ch) override {
62 Segment &segment = m_segments.emplace_back();
63 segment[0] = ch;
64
65 setp(std::to_address(segment.begin()) + 1, std::to_address(segment.end()));
66
67 // Anything but EOF means 'ok'.
68 return traits_type::not_eof(ch);
69 }
70
71 /// Apply 'sink' to each character in the trace text.
72 template <typename Sink>
73 void ForEach(Sink sink) const {
74 for (const Segment &segment : m_segments) {
75 for (const char &ch : segment) {
76 if (&ch == pptr()) {
77 break;
78 }
79 sink(ch);
80 }
81 }
82 }
83
84 /**
85 Apply 'sink' to each character in the trace text. Free each segment
86 when its contents have been consumed.
87 */
88 template <typename Sink>
89 void ForEachRemove(Sink sink) {
90 if (m_segments.empty()) {
91 assert(pptr() == nullptr && pbase() == nullptr && epptr() == nullptr);
92 } else {
93 while (!m_segments.empty()) {
94 for (char &ch : m_segments.front()) {
95 if (&ch == pptr()) {
96 setp(nullptr, nullptr);
97 assert(m_segments.size() == 1);
98 break;
99 }
100 sink(ch);
101 }
102 m_segments.pop_front();
103 }
104 }
105 }
106
107 /// Return a copy of the contents as a string. This may be expensive for
108 /// large traces, and is only intended for unit tests.
109 std::string ToString() const {
110 std::string result;
111 ForEach([&](char ch) { result += ch; });
112 return result;
113 }
114
115 private:
116 /// The sequence of segments.
118};
119
120/**
121 Trace in the form of plain text (i.e. no JSON tree), as used by
122 the Hypergraph optimizer.
123*/
124class UnstructuredTrace final {
125 public:
127
128 /// Get the stream in which to put the trace text.
129 std::ostream &stream() { return m_stream; }
130
132 const TraceBuffer &contents() const { return m_buffer; }
133
134 private:
135 /// The trace text.
137
138 /// The stream that formats text and appends it to m_buffer.
139 std::ostream m_stream;
140};
141
142// Shorthand functions.
143
144/// Fetch the ostream that we write optimizer trace into.
145inline std::ostream &Trace(THD *thd) {
146 return thd->opt_trace.unstructured_trace()->stream();
147}
148
149/// @returns 'true' if unstructured optimizer trace (as used by Hypergraph)
150/// is started.
151inline bool TraceStarted(THD *thd) {
152 return thd->opt_trace.is_started() &&
153 thd->opt_trace.unstructured_trace() != nullptr;
154}
155#endif
UnstructuredTrace * unstructured_trace()
Definition: opt_trace_context.h:275
bool is_started() const
Returns whether there is a current trace.
Definition: opt_trace_context.h:147
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:36
Opt_trace_context opt_trace
optimizer trace of current statement
Definition: sql_class.h:4064
This class is used for storing unstructured optimizer trace text (as used by the Hypergraph optimizer...
Definition: optimizer_trace.h:45
void ForEach(Sink sink) const
Apply 'sink' to each character in the trace text.
Definition: optimizer_trace.h:73
std::array< char, kSegmentSize > Segment
A consecutive buffer.
Definition: optimizer_trace.h:52
static constexpr size_t kSegmentSize
The size of each consecutive buffer.
Definition: optimizer_trace.h:48
int_type overflow(int_type ch) override
Called by std::ostream if the current segment is full.
Definition: optimizer_trace.h:61
std::deque< Segment > DequeType
The sequence of consecutive buffers.
Definition: optimizer_trace.h:54
std::string ToString() const
Return a copy of the contents as a string.
Definition: optimizer_trace.h:109
void ForEachRemove(Sink sink)
Apply 'sink' to each character in the trace text.
Definition: optimizer_trace.h:89
DequeType m_segments
The sequence of segments.
Definition: optimizer_trace.h:117
Trace in the form of plain text (i.e.
Definition: optimizer_trace.h:124
std::ostream m_stream
The stream that formats text and appends it to m_buffer.
Definition: optimizer_trace.h:139
UnstructuredTrace()
Definition: optimizer_trace.h:126
TraceBuffer m_buffer
The trace text.
Definition: optimizer_trace.h:136
TraceBuffer & contents()
Definition: optimizer_trace.h:131
const TraceBuffer & contents() const
Definition: optimizer_trace.h:132
std::ostream & stream()
Get the stream in which to put the trace text.
Definition: optimizer_trace.h:129
This contains the declaration of class Opt_trace_context, which is needed to declare THD.
std::ostream & Trace(THD *thd)
Fetch the ostream that we write optimizer trace into.
Definition: optimizer_trace.h:145
bool TraceStarted(THD *thd)
Definition: optimizer_trace.h:151
struct result result
Definition: result.h:34
Definition: result.h:30