yql_gc_transformer.cpp 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. #include "yql_gc_transformer.h"
  2. #include <yql/essentials/utils/yql_panic.h>
  3. namespace NYql {
  4. namespace {
  5. class TGcNodeTransformer : public TSyncTransformerBase {
  6. public:
  7. TGcNodeTransformer()
  8. {}
  9. TStatus DoTransform(TExprNode::TPtr input, TExprNode::TPtr& output, TExprContext& ctx) override {
  10. output = input;
  11. if (!CurrentThreshold)
  12. CurrentThreshold = ctx.GcConfig.Settings.NodeCountThreshold;
  13. if (ctx.NodeAllocationCounter < LastGcCount + CurrentThreshold) {
  14. return TStatus::Ok;
  15. }
  16. const auto oldSize = ctx.ExprNodes.size();
  17. const auto zombies = std::partition(ctx.ExprNodes.begin(), ctx.ExprNodes.end(), std::bind(std::logical_not<bool>(), std::bind(&TExprNode::Dead, std::placeholders::_1)));
  18. for (auto it = zombies; ctx.ExprNodes.cend() != it; ++it) {
  19. const auto dead = it->get();
  20. if (const auto hash = dead->GetHashAbove()) {
  21. const auto range = ctx.UniqueNodes.equal_range(hash);
  22. for (auto jt = range.first; range.second != jt;) {
  23. if (jt->second == dead) {
  24. jt = ctx.UniqueNodes.erase(jt);
  25. } else {
  26. ++jt;
  27. }
  28. }
  29. }
  30. }
  31. ctx.ExprNodes.erase(zombies, ctx.ExprNodes.cend());
  32. const auto liveSize = ctx.ExprNodes.size();
  33. Y_ABORT_UNLESS(liveSize >= ctx.UniqueNodes.size());
  34. // Update statistic.
  35. ++ctx.GcConfig.Statistics.CollectCount;
  36. ctx.GcConfig.Statistics.TotalCollectedNodes += oldSize - liveSize;
  37. LastGcCount = ctx.NodeAllocationCounter;
  38. // adjust next treshold
  39. CurrentThreshold = Max(ctx.GcConfig.Settings.NodeCountThreshold, liveSize);
  40. if (liveSize > ctx.NodesAllocationLimit) {
  41. ctx.AddError(YqlIssue(TPosition(), TIssuesIds::CORE_GC_NODES_LIMIT_EXCEEDED, TStringBuilder()
  42. << "Too many allocated nodes, allowed: " << ctx.NodesAllocationLimit
  43. << ", current: " << liveSize));
  44. return TStatus::Error;
  45. }
  46. const auto poolSize = ctx.StringPool.MemoryAllocated() + ctx.StringPool.MemoryWaste();
  47. if (poolSize > ctx.StringsAllocationLimit) {
  48. ctx.AddError(YqlIssue(TPosition(), TIssuesIds::CORE_GC_STRINGS_LIMIT_EXCEEDED, TStringBuilder()
  49. << "Too large string pool, allowed: " << ctx.StringsAllocationLimit
  50. << ", current: " << poolSize));
  51. return TStatus::Error;
  52. }
  53. return TStatus::Ok;
  54. }
  55. void Rewind() final {
  56. LastGcCount = 0;
  57. CurrentThreshold = 0;
  58. }
  59. private:
  60. ui64 LastGcCount = 0;
  61. ui64 CurrentThreshold = 0;
  62. };
  63. }
  64. TAutoPtr<IGraphTransformer> CreateGcNodeTransformer() {
  65. return new TGcNodeTransformer();
  66. }
  67. }