Skip to content

Commit 2df69b3

Browse files
linevdpiparo
authored andcommitted
[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 1eafcbc commit 2df69b3

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

826826
if (method != nullptr) {
827827
if (can_use_plain) {
828-
call = new TMethodCall();
829-
call->InitWithPrototype(obj_cl, method_name, prototype.IsNull() ? nullptr : prototype.Data());
830-
} else
828+
// prevent creation of huge cache
829+
if (fExeCache.size() > 1000)
830+
fExeCache.clear();
831+
auto iter = fExeCache.find(method);
832+
if (iter != fExeCache.end()) {
833+
call = iter->second.get();
834+
} else {
835+
call = new TMethodCall();
836+
call->InitWithPrototype(obj_cl, method_name, prototype.IsNull() ? nullptr : prototype.Data());
837+
fExeCache.emplace(method, std::unique_ptr<TMethodCall>(call));
838+
}
839+
} else {
831840
call = new TMethodCall(obj_cl, method_name, call_args.Data());
841+
garbage.Add(call);
842+
}
832843
if (debug)
833844
debug->append(TString::Format("Calling obj->%s(%s);\n", method_name, call_args.Data()).Data());
834845
} else {
835846
call = new TMethodCall(funcname.Data(), call_args.Data());
847+
garbage.Add(call);
836848
if (debug)
837849
debug->append(TString::Format("Calling %s(%s);\n", funcname.Data(), call_args.Data()).Data());
838850
}
839851

840-
garbage.Add(call);
841-
842852
if (!call->IsValid()) {
843853
if (debug)
844854
debug->append("Fail: invalid TMethodCall\n");

0 commit comments

Comments
 (0)