interface.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include "interface.h"
  2. #include <array>
  3. #include <util/string/builder.h>
  4. #include <util/generic/hash.h>
  5. #include <util/generic/hash_set.h>
  6. #include <library/cpp/disjoint_sets/disjoint_sets.h>
  7. namespace NYql {
  8. namespace {
  9. std::array<TStringBuf,6> Prefixes = {
  10. "",
  11. " ",
  12. " ",
  13. " ",
  14. " ",
  15. " "
  16. };
  17. TStringBuf Prefix(int level) {
  18. return level < (int)Prefixes.size()
  19. ? Prefixes[level]
  20. : Prefixes.back();
  21. }
  22. void PrettyPrintVar(TStringBuilder& b, const IOptimizer::TInput* input, IOptimizer::TVarId varId) {
  23. const auto& [relno, varno] = varId;
  24. auto varName = input
  25. ? input->Rels[relno-1].TargetVars[varno-1].Name
  26. : '\0';
  27. if (!varName) {
  28. b << "(" << relno << "," << varno << ")";
  29. } else {
  30. b << varName;
  31. }
  32. }
  33. void PrettyPrintVars(TStringBuilder& b, const IOptimizer::TInput* input, const std::vector<IOptimizer::TVarId>& vars) {
  34. for (ui32 j = 0; j < vars.size(); ++j) {
  35. PrettyPrintVar(b, input, vars[j]);
  36. if (j != vars.size() - 1) {
  37. b << ",";
  38. }
  39. }
  40. }
  41. void PrettyPrintNode(int level, TStringBuilder& b, const IOptimizer::TOutput& output, int id) {
  42. TStringBuf prefix = Prefix(level);
  43. const auto& node = output.Nodes[id];
  44. switch (node.Mode) {
  45. case IOptimizer::EJoinType::Unknown: b << prefix << " Node\n"; break;
  46. case IOptimizer::EJoinType::Inner: b << prefix << " Inner Join\n"; break;
  47. case IOptimizer::EJoinType::Left: b << prefix << " Left Join\n"; break;
  48. case IOptimizer::EJoinType::Right: b << prefix << " Right Join\n"; break;
  49. default: b << prefix << " Unknown\n"; break;
  50. }
  51. switch (node.Strategy) {
  52. case IOptimizer::EJoinStrategy::Hash: b << prefix << " Hash Strategy\n"; break;
  53. case IOptimizer::EJoinStrategy::Loop: b << prefix << " Loop Strategy\n"; break;
  54. default: break;
  55. }
  56. if (!node.Rels.empty())
  57. {
  58. b << prefix << " Rels: [";
  59. for (int i = 0; i < (int)node.Rels.size()-1; i++) {
  60. b << node.Rels[i] << ",";
  61. }
  62. b << node.Rels.back();
  63. b << "]\n";
  64. }
  65. {
  66. if (!node.LeftVars.empty() && !node.RightVars.empty()) {
  67. b << prefix << " Op: ";
  68. PrettyPrintVars(b, output.Input, node.LeftVars);
  69. b << " = ";
  70. PrettyPrintVars(b, output.Input, node.RightVars);
  71. b << "\n";
  72. }
  73. }
  74. if (node.Outer != -1) {
  75. b << prefix << " {\n";
  76. PrettyPrintNode(level+1, b, output, node.Outer);
  77. b << prefix << " }\n";
  78. }
  79. if (node.Inner != -1) {
  80. b << prefix << " {\n";
  81. PrettyPrintNode(level+1, b, output, node.Inner);
  82. b << prefix << " }\n";
  83. }
  84. }
  85. void PrettyPrintRel(TStringBuilder& b, const IOptimizer::TInput* input, const auto& relId) {
  86. const auto& rel = input->Rels[relId - 1];
  87. b << "{";
  88. b << "rows: " << rel.Rows << ",";
  89. b << "cost: " << rel.TotalCost << ",";
  90. b << "vars: [";
  91. for (ui32 i = 0; i < rel.TargetVars.size(); i++) {
  92. PrettyPrintVar(b, input, {relId, i + 1});
  93. if (i != rel.TargetVars.size() - 1) {
  94. b << ", ";
  95. }
  96. }
  97. b << "]";
  98. b << "}";
  99. }
  100. } // namespace
  101. TString IOptimizer::TOutput::ToString(bool printCost) const {
  102. TStringBuilder b;
  103. if (printCost) {
  104. char buf[1024];
  105. snprintf(buf, sizeof(buf), "%.2lf", Rows);
  106. b << "Rows: " << buf << "\n";
  107. snprintf(buf, sizeof(buf), "%.2lf", TotalCost);
  108. b << "TotalCost: " << buf << "\n";
  109. }
  110. b << "{\n";
  111. if (!Nodes.empty()) {
  112. PrettyPrintNode(0, b, *this, 0);
  113. }
  114. b << "}\n";
  115. return b;
  116. }
  117. TString IOptimizer::TInput::ToString() const {
  118. TStringBuilder b;
  119. b << "Rels: [";
  120. for (ui32 i = 0; i < Rels.size(); ++i) {
  121. PrettyPrintRel(b, this, i + 1);
  122. if (i != Rels.size() - 1) {
  123. b << ",\n";
  124. }
  125. }
  126. b << "]\n";
  127. b << "EqClasses: [";
  128. for (ui32 i = 0; i < EqClasses.size(); ++i) {
  129. b << "[";
  130. PrettyPrintVars(b, this, EqClasses[i].Vars);
  131. b << "]";
  132. if (i != EqClasses.size() - 1) {
  133. b << ",";
  134. }
  135. }
  136. b << "]\n";
  137. return b;
  138. }
  139. void IOptimizer::TInput::Normalize() {
  140. using TId = TDisjointSets::TElement;
  141. THashMap<TVarId, TId> var2id;
  142. std::vector<TVarId> id2var;
  143. TId curId = 1;
  144. for (auto& eq : EqClasses) {
  145. for (auto& v : eq.Vars) {
  146. auto& id = var2id[v];
  147. if (id == 0) {
  148. id = curId;
  149. id2var.resize(curId + 1);
  150. id2var[curId] = v;
  151. ++curId;
  152. }
  153. }
  154. }
  155. TDisjointSets u(curId + 1);
  156. for (auto& eq : EqClasses) {
  157. Y_ABORT_UNLESS(!eq.Vars.empty());
  158. ui32 i = 0;
  159. TId first = var2id[eq.Vars[i++]];
  160. for (; i < eq.Vars.size(); ++i) {
  161. TId id = var2id[eq.Vars[i]];
  162. u.UnionSets(first, id);
  163. }
  164. }
  165. THashMap<TId, THashSet<TId>> eqClasses;
  166. for (auto& eq : EqClasses) {
  167. for (auto& var : eq.Vars) {
  168. auto id = var2id[var];
  169. auto canonicalId = u.CanonicSetElement(id);
  170. eqClasses[canonicalId].emplace(id);
  171. }
  172. }
  173. EqClasses.clear();
  174. for (auto& [_, ids]: eqClasses) {
  175. TEq eqClass;
  176. eqClass.Vars.reserve(ids.size());
  177. for (auto id : ids) {
  178. eqClass.Vars.emplace_back(id2var[id]);
  179. }
  180. std::sort(eqClass.Vars.begin(), eqClass.Vars.end());
  181. EqClasses.emplace_back(std::move(eqClass));
  182. }
  183. }
  184. }