Skip to content

Commit

Permalink
add a BPFModule API to disable rw_engine sscanf/snprintf functions
Browse files Browse the repository at this point in the history
Currently, for every table of a module, corresponding
key/value sscanf/snprintf functions will be generated.
These functions are mostly used for python API to
facilitate passing keys between python and C++.

It is a known issue that these sscanf/snprintf functions
can consume a lot of system resources esp. memory for
large arrays. Commit 22eae8c ("Use late-binding to
finalize snprintf/sscanf") avoids unnecessary code
generation for snprintf/sscanf until they are called.
Even with this commit, however, the overhead can still
be significant for large arrays.

For example, the following large array,
  #define TCP6_RXMIT_BUCKET_BITS 18
  struct tcp6_rxmit_tbl {
    __u64 buckets[1 << TCP6_RXMIT_BUCKET_BITS];
  };
  BPF_ARRAY(rxmit_marking_map, struct tcp6_rxmit_tbl, 1);
is used inside Facebook.
If it is added to examples/cpp/HelloWorld.cpp,
the HelloWorld RSS memory will increase from 7MB to
370MB.

This patch add a BPFModule API and a C++ API to
disable rw_engine sscanf/snprintf function through additional
constructor parameters. rw_engine support for Python is not affected.

Signed-off-by: Yonghong Song <[email protected]>
  • Loading branch information
yonghong-song committed Feb 23, 2018
1 parent 40fd669 commit db7b8eb
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 11 deletions.
5 changes: 3 additions & 2 deletions src/cc/api/BPF.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ class BPF {
public:
static const int BPF_MAX_STACK_DEPTH = 127;

explicit BPF(unsigned int flag = 0, TableStorage* ts = nullptr)
: flag_(flag), bpf_module_(new BPFModule(flag, ts)) {}
explicit BPF(unsigned int flag = 0, TableStorage* ts = nullptr,
bool rw_engine_enabled = true)
: flag_(flag), bpf_module_(new BPFModule(flag, ts, rw_engine_enabled)) {}
StatusTuple init(const std::string& bpf_program,
const std::vector<std::string>& cflags = {},
const std::vector<USDT>& usdt = {});
Expand Down
25 changes: 18 additions & 7 deletions src/cc/bpf_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ class MyMemoryManager : public SectionMemoryManager {
map<string, tuple<uint8_t *, uintptr_t>> *sections_;
};

BPFModule::BPFModule(unsigned flags, TableStorage *ts)
BPFModule::BPFModule(unsigned flags, TableStorage *ts, bool rw_engine_enabled)
: flags_(flags),
rw_engine_enabled_(rw_engine_enabled),
used_b_loader_(false),
ctx_(new LLVMContext),
id_(std::to_string((uintptr_t)this)),
Expand Down Expand Up @@ -530,6 +531,8 @@ int BPFModule::annotate() {
}

StatusTuple BPFModule::sscanf(string fn_name, const char *str, void *val) {
if (!rw_engine_enabled_)
return StatusTuple(-1, "rw_engine not enabled");
auto fn =
(int (*)(const char *, void *))rw_engine_->getFunctionAddress(fn_name);
if (!fn)
Expand All @@ -542,6 +545,8 @@ StatusTuple BPFModule::sscanf(string fn_name, const char *str, void *val) {

StatusTuple BPFModule::snprintf(string fn_name, char *str, size_t sz,
const void *val) {
if (!rw_engine_enabled_)
return StatusTuple(-1, "rw_engine not enabled");
auto fn = (int (*)(char *, size_t,
const void *))rw_engine_->getFunctionAddress(fn_name);
if (!fn)
Expand Down Expand Up @@ -937,8 +942,10 @@ int BPFModule::load_b(const string &filename, const string &proto_filename) {
used_b_loader_ = true;
if (int rc = b_loader.parse(&*mod_, filename, proto_filename, *ts_, id_))
return rc;
if (int rc = annotate())
return rc;
if (rw_engine_enabled_) {
if (int rc = annotate())
return rc;
}
if (int rc = finalize())
return rc;
return 0;
Expand All @@ -956,8 +963,10 @@ int BPFModule::load_c(const string &filename, const char *cflags[], int ncflags)
}
if (int rc = load_cfile(filename, false, cflags, ncflags))
return rc;
if (int rc = annotate())
return rc;
if (rw_engine_enabled_) {
if (int rc = annotate())
return rc;
}
if (int rc = finalize())
return rc;
return 0;
Expand All @@ -971,8 +980,10 @@ int BPFModule::load_string(const string &text, const char *cflags[], int ncflags
}
if (int rc = load_cfile(text, true, cflags, ncflags))
return rc;
if (int rc = annotate())
return rc;
if (rw_engine_enabled_) {
if (int rc = annotate())
return rc;
}

if (int rc = finalize())
return rc;
Expand Down
3 changes: 2 additions & 1 deletion src/cc/bpf_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class BPFModule {
const void *val);

public:
BPFModule(unsigned flags, TableStorage *ts = nullptr);
BPFModule(unsigned flags, TableStorage *ts = nullptr, bool rw_engine_enabled = true);
~BPFModule();
int load_b(const std::string &filename, const std::string &proto_filename);
int load_c(const std::string &filename, const char *cflags[], int ncflags);
Expand Down Expand Up @@ -120,6 +120,7 @@ class BPFModule {

private:
unsigned flags_; // 0x1 for printing
bool rw_engine_enabled_;
bool used_b_loader_;
std::string filename_;
std::string proto_filename_;
Expand Down
3 changes: 2 additions & 1 deletion tests/cc/test_array_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ TEST_CASE("test array table", "[array_table]") {
BPF_TABLE("array", int, int, myarray, 128);
)";

ebpf::BPF bpf;
// turn off the rw_engine
ebpf::BPF bpf(0, nullptr, false);
ebpf::StatusTuple res(0);
res = bpf.init(BPF_PROGRAM);
REQUIRE(res.code() == 0);
Expand Down

0 comments on commit db7b8eb

Please sign in to comment.