Skip to content

Commit efe3e59

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 d0e9eca commit efe3e59

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
@@ -813,20 +813,30 @@ Bool_t TRootSnifferFull::ProduceExe(const std::string &path, const std::string &
813813

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

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

0 commit comments

Comments
 (0)