-
Notifications
You must be signed in to change notification settings - Fork 4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
疑似keytable内存泄漏 #2756
Comments
自己起的线程中使用bthread_keytable吗? |
@chenBright 不是,就是rpc处理的bthread中使用的 |
使用bthread-local的场景是什么样的呢@lsdh-fei |
@MJY-HUST 没有单独使用bthread-local,就是task_runner中的,我门最近把brpc从1.8升级到了1.10,然后就发现新版有内存泄漏,LogStream占用了大量内存,看了下brpc源代码,发现log stream的buf是存在keytable中,然后就怀疑是keytable的问题,然后看vars监控,发现keytable的数量一直在不断增长,所以才怀疑是新版的改动导致的 |
我提供一个个人的角度,可以讨论一下。 因为新的keytable的策略,是return到一个pthread 的thread local的list中。但没办法保证的是,同一个keytable被borrow后,会被return到同一个pthread里。 本来其实也没什么问题,只要等待足够时间,每个pthread中,就会create足够的keytable。但是可能,目前的一些task的调度策略,会使得pthread中的keytable数量像波浪一样震荡,使得keytable稳定的总数大大增加。 可以看这么一个例子 void* print_log(void *) {
std::random_device rd;
std::mt19937 mt{rd()};
std::uniform_int_distribution<uint64_t> uid(0, 100000);
bthread_usleep(50000 + uid(mt));
LOG(INFO) << "some log here xxx";
return NULL;
}
class GreeterImpl final : public Greeter {
void SayHello(google::protobuf::RpcController* controller, const HelloRequest* request, HelloReply* response, google::protobuf::Closure* done) override {
brpc::ClosureGuard done_guard(done);
brpc::Controller* cntl = static_cast<brpc::Controller*>(controller);
(void)print_log(NULL);
std::string message = "Hello " + request->name() + "!\n";
response->set_message(message);
}
}; 先做sleep,再进行LOG(相当于使用keytable),可以看到keytable的数量非常稳定。因为这里,每个pthread里,有一个keytable就可以了。 但我们换一下位置 void* print_log(void *) {
std::random_device rd;
std::mt19937 mt{rd()};
std::uniform_int_distribution<uint64_t> uid(0, 100000);
LOG(INFO) << "some log here xxx";
bthread_usleep(50000 + uid(mt));
return NULL;
}
class GreeterImpl final : public Greeter {
void SayHello(google::protobuf::RpcController* controller, const HelloRequest* request, HelloReply* response, google::protobuf::Closure* done) override {
brpc::ClosureGuard done_guard(done);
brpc::Controller* cntl = static_cast<brpc::Controller*>(controller);
(void)print_log(NULL);
std::string message = "Hello " + request->name() + "!\n";
response->set_message(message);
}
}; 这里从统计意义上来说,增长可能会一直存在,因为当前worker的task sleep了(或者是等待某个锁),之后它好像会尝试从其他队列steal一个pendding的任务。随着这些任务都sleep(或者都block在某个锁上),这个work所在的pthread的存量keyTable会被持续消耗。而且这些keytable大概率不会被return到这个pthread了。 所以,pthread中的keytables,不是维持在一个较为稳定的状态,而是有着潮水一样的涨落。随着borrow的失败,只能不停的new新的keytable |
是的,假设每个bthread都持有keytable的前提下,如果pendding的bthread数量过多(持续增长),那么内存消耗是无法避免的。 |
这个解决方案看上去很棒。 看上去,只需要对return_keytable逻辑进行一些调整。 期待大佬们给出修复。 |
@MJY-HUST 10月节后会发新版本,能赶上新版本修复这个问题吗? |
|
Describe the bug (描述bug)
升级1.10之后,内存会不断增长,在vars界面查看,发现bthread_keytable_count在不断增长,我理解keytable是thread local的,thread销毁后也会跟着销毁,不应该无限增长
To Reproduce (复现方法)
使用1.10之后就会出现,但是用1.8就不存在泄漏
Expected behavior (期望行为)
keytable对象数量维持动态平衡
Versions (各种版本)
OS: Ubuntu 20.04.3 LTS
Compiler: clang8
brpc: 1.10
protobuf: 3.15.8
Additional context/screenshots (更多上下文/截图)
The text was updated successfully, but these errors were encountered: