[adb] Optimize fdevent machinery
- Use one fewer heap allocation per fdevent object - Lazy-init the fdevent context Bug: 151239696 Test: various adb commands on Win/Linux Change-Id: Ic7de207b30495e618f187e097c0276ad42c34005 Merged-In: Ic7de207b30495e618f187e097c0276ad42c34005
This commit is contained in:
parent
2488c21d8b
commit
4eb910e82e
5 changed files with 51 additions and 51 deletions
|
@ -63,7 +63,10 @@ fdevent* fdevent_context::Create(unique_fd fd, std::variant<fd_func, fd_func2> f
|
|||
|
||||
int fd_num = fd.get();
|
||||
|
||||
fdevent* fde = new fdevent();
|
||||
auto [it, inserted] = this->installed_fdevents_.emplace(fd_num, fdevent{});
|
||||
CHECK(inserted);
|
||||
|
||||
fdevent* fde = &it->second;
|
||||
fde->id = fdevent_id_++;
|
||||
fde->state = 0;
|
||||
fde->fd = std::move(fd);
|
||||
|
@ -76,10 +79,6 @@ fdevent* fdevent_context::Create(unique_fd fd, std::variant<fd_func, fd_func2> f
|
|||
LOG(ERROR) << "failed to set non-blocking mode for fd " << fde->fd.get();
|
||||
}
|
||||
|
||||
auto [it, inserted] = this->installed_fdevents_.emplace(fd_num, fde);
|
||||
CHECK(inserted);
|
||||
UNUSED(it);
|
||||
|
||||
this->Register(fde);
|
||||
return fde;
|
||||
}
|
||||
|
@ -92,12 +91,12 @@ unique_fd fdevent_context::Destroy(fdevent* fde) {
|
|||
|
||||
this->Unregister(fde);
|
||||
|
||||
auto erased = this->installed_fdevents_.erase(fde->fd.get());
|
||||
unique_fd fd = std::move(fde->fd);
|
||||
|
||||
auto erased = this->installed_fdevents_.erase(fd.get());
|
||||
CHECK_EQ(1UL, erased);
|
||||
|
||||
unique_fd result = std::move(fde->fd);
|
||||
delete fde;
|
||||
return result;
|
||||
return fd;
|
||||
}
|
||||
|
||||
void fdevent_context::Add(fdevent* fde, unsigned events) {
|
||||
|
@ -123,9 +122,9 @@ std::optional<std::chrono::milliseconds> fdevent_context::CalculatePollDuration(
|
|||
|
||||
for (const auto& [fd, fde] : this->installed_fdevents_) {
|
||||
UNUSED(fd);
|
||||
auto timeout_opt = fde->timeout;
|
||||
auto timeout_opt = fde.timeout;
|
||||
if (timeout_opt) {
|
||||
auto deadline = fde->last_active + *timeout_opt;
|
||||
auto deadline = fde.last_active + *timeout_opt;
|
||||
auto time_left = duration_cast<std::chrono::milliseconds>(deadline - now);
|
||||
if (time_left < 0ms) {
|
||||
time_left = 0ms;
|
||||
|
@ -194,11 +193,13 @@ static std::unique_ptr<fdevent_context> fdevent_create_context() {
|
|||
#endif
|
||||
}
|
||||
|
||||
static auto& g_ambient_fdevent_context =
|
||||
*new std::unique_ptr<fdevent_context>(fdevent_create_context());
|
||||
static auto& g_ambient_fdevent_context() {
|
||||
static auto context = fdevent_create_context().release();
|
||||
return context;
|
||||
}
|
||||
|
||||
static fdevent_context* fdevent_get_ambient() {
|
||||
return g_ambient_fdevent_context.get();
|
||||
return g_ambient_fdevent_context();
|
||||
}
|
||||
|
||||
fdevent* fdevent_create(int fd, fd_func func, void* arg) {
|
||||
|
@ -256,5 +257,6 @@ size_t fdevent_installed_count() {
|
|||
}
|
||||
|
||||
void fdevent_reset() {
|
||||
g_ambient_fdevent_context = fdevent_create_context();
|
||||
auto old = std::exchange(g_ambient_fdevent_context(), fdevent_create_context().release());
|
||||
delete old;
|
||||
}
|
||||
|
|
|
@ -52,6 +52,20 @@ struct fdevent_event {
|
|||
unsigned events;
|
||||
};
|
||||
|
||||
struct fdevent final {
|
||||
uint64_t id;
|
||||
|
||||
unique_fd fd;
|
||||
int force_eof = 0;
|
||||
|
||||
uint16_t state = 0;
|
||||
std::optional<std::chrono::milliseconds> timeout;
|
||||
std::chrono::steady_clock::time_point last_active;
|
||||
|
||||
std::variant<fd_func, fd_func2> func;
|
||||
void* arg = nullptr;
|
||||
};
|
||||
|
||||
struct fdevent_context {
|
||||
public:
|
||||
virtual ~fdevent_context() = default;
|
||||
|
@ -113,7 +127,7 @@ struct fdevent_context {
|
|||
std::atomic<bool> terminate_loop_ = false;
|
||||
|
||||
protected:
|
||||
std::unordered_map<int, fdevent*> installed_fdevents_;
|
||||
std::unordered_map<int, fdevent> installed_fdevents_;
|
||||
|
||||
private:
|
||||
uint64_t fdevent_id_ = 0;
|
||||
|
@ -121,20 +135,6 @@ struct fdevent_context {
|
|||
std::deque<std::function<void()>> run_queue_ GUARDED_BY(run_queue_mutex_);
|
||||
};
|
||||
|
||||
struct fdevent {
|
||||
uint64_t id;
|
||||
|
||||
unique_fd fd;
|
||||
int force_eof = 0;
|
||||
|
||||
uint16_t state = 0;
|
||||
std::optional<std::chrono::milliseconds> timeout;
|
||||
std::chrono::steady_clock::time_point last_active;
|
||||
|
||||
std::variant<fd_func, fd_func2> func;
|
||||
void* arg = nullptr;
|
||||
};
|
||||
|
||||
// Backwards compatibility shims that forward to the global fdevent_context.
|
||||
fdevent* fdevent_create(int fd, fd_func func, void* arg);
|
||||
fdevent* fdevent_create(int fd, fd_func2 func, void* arg);
|
||||
|
|
|
@ -155,15 +155,15 @@ void fdevent_context_epoll::Loop() {
|
|||
event_map[fde] = events;
|
||||
}
|
||||
|
||||
for (const auto& [fd, fde] : installed_fdevents_) {
|
||||
for (auto& [fd, fde] : installed_fdevents_) {
|
||||
unsigned events = 0;
|
||||
if (auto it = event_map.find(fde); it != event_map.end()) {
|
||||
if (auto it = event_map.find(&fde); it != event_map.end()) {
|
||||
events = it->second;
|
||||
}
|
||||
|
||||
if (events == 0) {
|
||||
if (fde->timeout) {
|
||||
auto deadline = fde->last_active + *fde->timeout;
|
||||
if (fde.timeout) {
|
||||
auto deadline = fde.last_active + *fde.timeout;
|
||||
if (deadline < post_poll) {
|
||||
events |= FDE_TIMEOUT;
|
||||
}
|
||||
|
@ -171,13 +171,13 @@ void fdevent_context_epoll::Loop() {
|
|||
}
|
||||
|
||||
if (events != 0) {
|
||||
LOG(DEBUG) << dump_fde(fde) << " got events " << std::hex << std::showbase
|
||||
LOG(DEBUG) << dump_fde(&fde) << " got events " << std::hex << std::showbase
|
||||
<< events;
|
||||
fde_events.push_back({fde, events});
|
||||
fde->last_active = post_poll;
|
||||
fde_events.push_back({&fde, events});
|
||||
fde.last_active = post_poll;
|
||||
}
|
||||
}
|
||||
this->HandleEvents(std::move(fde_events));
|
||||
this->HandleEvents(fde_events);
|
||||
fde_events.clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -47,12 +47,7 @@ struct fdevent_context_epoll final : public fdevent_context {
|
|||
protected:
|
||||
virtual void Interrupt() final;
|
||||
|
||||
public:
|
||||
// All operations to fdevent should happen only in the main thread.
|
||||
// That's why we don't need a lock for fdevent.
|
||||
std::unordered_map<int, fdevent*> epoll_node_map_;
|
||||
std::list<fdevent*> pending_list_;
|
||||
|
||||
private:
|
||||
unique_fd epoll_fd_;
|
||||
unique_fd interrupt_fd_;
|
||||
fdevent* interrupt_fde_ = nullptr;
|
||||
|
|
|
@ -103,24 +103,27 @@ static std::string dump_pollfds(const std::vector<adb_pollfd>& pollfds) {
|
|||
void fdevent_context_poll::Loop() {
|
||||
main_thread_id_ = android::base::GetThreadId();
|
||||
|
||||
std::vector<adb_pollfd> pollfds;
|
||||
std::vector<fdevent_event> poll_events;
|
||||
|
||||
while (true) {
|
||||
if (terminate_loop_) {
|
||||
break;
|
||||
}
|
||||
|
||||
D("--- --- waiting for events");
|
||||
std::vector<adb_pollfd> pollfds;
|
||||
pollfds.clear();
|
||||
for (const auto& [fd, fde] : this->installed_fdevents_) {
|
||||
adb_pollfd pfd;
|
||||
pfd.fd = fd;
|
||||
pfd.events = 0;
|
||||
if (fde->state & FDE_READ) {
|
||||
if (fde.state & FDE_READ) {
|
||||
pfd.events |= POLLIN;
|
||||
}
|
||||
if (fde->state & FDE_WRITE) {
|
||||
if (fde.state & FDE_WRITE) {
|
||||
pfd.events |= POLLOUT;
|
||||
}
|
||||
if (fde->state & FDE_ERROR) {
|
||||
if (fde.state & FDE_ERROR) {
|
||||
pfd.events |= POLLERR;
|
||||
}
|
||||
#if defined(__linux__)
|
||||
|
@ -147,7 +150,6 @@ void fdevent_context_poll::Loop() {
|
|||
}
|
||||
|
||||
auto post_poll = std::chrono::steady_clock::now();
|
||||
std::vector<fdevent_event> poll_events;
|
||||
|
||||
for (const auto& pollfd : pollfds) {
|
||||
unsigned events = 0;
|
||||
|
@ -170,7 +172,7 @@ void fdevent_context_poll::Loop() {
|
|||
|
||||
auto it = this->installed_fdevents_.find(pollfd.fd);
|
||||
CHECK(it != this->installed_fdevents_.end());
|
||||
fdevent* fde = it->second;
|
||||
fdevent* fde = &it->second;
|
||||
|
||||
if (events == 0) {
|
||||
if (fde->timeout) {
|
||||
|
@ -187,7 +189,8 @@ void fdevent_context_poll::Loop() {
|
|||
fde->last_active = post_poll;
|
||||
}
|
||||
}
|
||||
this->HandleEvents(std::move(poll_events));
|
||||
this->HandleEvents(poll_events);
|
||||
poll_events.clear();
|
||||
}
|
||||
|
||||
main_thread_id_.reset();
|
||||
|
|
Loading…
Reference in a new issue