Skip to content

Commit 88f0726

Browse files
committed
[http] keep cache for TMethodCall objects
When exe.json executed for same method many times create TMethodCall once and reuse it. Should significantly reduce memory fragmentation from cling and probably avoid memory leaks.
1 parent 7eab48e commit 88f0726

2 files changed

Lines changed: 20 additions & 5 deletions

File tree

net/httpsniff/inc/TRootSnifferFull.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@
1414

1515
#include "TRootSniffer.h"
1616
#include <string>
17+
#include <memory>
18+
#include <map>
1719

1820
class TMemFile;
21+
class TMethodCall;
22+
class TMethod;
1923

2024
class TRootSnifferFull : public TRootSniffer {
2125
protected:
2226
TMemFile *fMemFile{nullptr}; ///<! file used to manage streamer infos
2327
TList *fSinfo{nullptr}; ///<! last produced streamer info
28+
std::map<const TMethod *, std::unique_ptr<TMethodCall>> fExeCache; ///<! cache for exe.json invocation
2429

2530
void ScanObjectProperties(TRootSnifferScanRec &rec, TObject *obj) override;
2631

net/httpsniff/src/TRootSnifferFull.cxx

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -814,20 +814,30 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
814814

815815
if (method != nullptr) {
816816
if (can_use_plain) {
817-
call = new TMethodCall();
818-
call->InitWithPrototype(obj_cl, method_name, prototype.IsNull() ? nullptr : prototype.Data());
819-
} else
817+
// prevent creation of huge cache
818+
if (fExeCache.size() > 1000)
819+
fExeCache.clear();
820+
auto iter = fExeCache.find(method);
821+
if (iter != fExeCache.end()) {
822+
call = iter->second.get();
823+
} else {
824+
call = new TMethodCall();
825+
call->InitWithPrototype(obj_cl, method_name, prototype.IsNull() ? nullptr : prototype.Data());
826+
fExeCache.emplace(method, std::unique_ptr<TMethodCall>(call));
827+
}
828+
} else {
820829
call = new TMethodCall(obj_cl, method_name, call_args.Data());
830+
garbage.Add(call);
831+
}
821832
if (debug)
822833
debug->append(TString::Format("Calling obj->%s(%s);\n", method_name, call_args.Data()).Data());
823834
} else {
824835
call = new TMethodCall(funcname.Data(), call_args.Data());
836+
garbage.Add(call);
825837
if (debug)
826838
debug->append(TString::Format("Calling %s(%s);\n", funcname.Data(), call_args.Data()).Data());
827839
}
828840

829-
garbage.Add(call);
830-
831841
if (!call->IsValid()) {
832842
if (debug)
833843
debug->append("Fail: invalid TMethodCall\n");

0 commit comments

Comments
 (0)