Refactor Selectables. Add support for selectable priorities#192
Refactor Selectables. Add support for selectable priorities#192lguohan merged 16 commits intosonic-net:masterfrom
Conversation
common/ipaddress.h
Outdated
| public: | ||
| IpAddress() {} | ||
| IpAddress(const ip_addr_t &ip) { m_ip = ip; } | ||
| IpAddress(const ip_addr_t &ip) : m_ip(ip) {} |
There was a problem hiding this comment.
m_ip [](start = 37, length = 4)
Could you separate simple refactoring code like this into a smaller PR? so we could focus on more difficult one. #Closed
There was a problem hiding this comment.
I can, but it will take more time to extract all the changes and revert them back. Can you please consider to check them? They're tiny and follows just a few easy patterns:
func(object obj) -> func(const object& obj)
,
for(auto obj: object) -> for (const auto& obj: object)
'''
Class1::Class1(int var1)
{
m_var_1 = var1;
}
to
Class1::Class1(int var1) : m_var_1(var1) {}
#Closed
There was a problem hiding this comment.
I am thinking 'selectable improvement' as an experiment feature (not mature now). And other simple one are definitely good contribution to existing codebase. Considering the possibility of future reverting and/or conflicting, it's good to separate. Large amount of files in a PR always harm.
In reply to: 178991122 [](ancestors = 178991122)
There was a problem hiding this comment.
I've removed the other changes. I kept only one bug with the missed va_end()
| ~Select(); | ||
|
|
||
| /* Add object for select */ | ||
| void addSelectable(Selectable *selectable); |
There was a problem hiding this comment.
addSelectable [](start = 9, length = 13)
suggest move all priority setting as addSelectable parameter, so no need to modify all the related classes. #Closed
There was a problem hiding this comment.
The classes are already changed. These changes won't affect any client code.
Also, I don't like to add information about priority into Select class.
Following the principle of Single Responsibility I want Select class only work for polling, not for something else.
Also, it's not easy to change Select::addSelectables() method which expects vector of Selectables.
Also, is makes Select class more complicated, we need to store and operate on the priority, which is Selectable attribute. #Pending
There was a problem hiding this comment.
Got your idea. Let me correct my comment. I suggest move all priority setting as function call to Selectable (not Select), keep original constructor signature, so no need to modify all the related sub classes. Another benefit is that all previous code with default priority will keep previous behavior. If any future user would like to apply different priority assignment, he just is able to do so explicitly.
Since all the sub classes has not used pri at all, keep all the modification in base class.
In reply to: 178991671 [](ancestors = 178991671)
There was a problem hiding this comment.
I don't agree with you. As soon as we create separate method to change priority it will not work as expected. For example, You create a Selectable, then add it into Select object and then change its priority. It will broke Select object, because it didn't expect anyone changes Selectable objects in the queue.
Also it's bad from design viewpoint. The priority property is 'CREATE_AND_SET' property in SAI terms. We don't want to change it as it created.
|
You mentioned "To support this feature Selectable interface was changed significantly." |
|
I must change Selectable interface because: In this interface: readMe() allowed us to read information from Selectable which file descriptor signaled. Also I changed the previous Selectable interface because it leaked Select class methods into Selectables. |
common/select.h
Outdated
|
|
||
| /* Add file-descriptor for select */ | ||
| void addFd(int fd); | ||
| /* Add multiple messages for select */ |
There was a problem hiding this comment.
messages [](start = 20, length = 8)
objects #Closed
common/selectable.h
Outdated
| /* Read a message from the socket */ | ||
| virtual void readMe() = 0; | ||
| private: | ||
| int m_priority; |
There was a problem hiding this comment.
m_priority [](start = 8, length = 10)
Add some comment about the definition. The larger, the higher priority? #Closed
common/selectable.h
Outdated
| bool operator()(const Selectable* a, const Selectable* b) const | ||
| { | ||
| if (a->getPri() == b->getPri()) | ||
| return a > b; |
There was a problem hiding this comment.
a > b [](start = 23, length = 5)
Why define the order this way? The intuitive understanding is they are equal. #Closed
There was a problem hiding this comment.
Because std::set requires a functional object which defines order. By default it's std::less.
But I've defined my own order
http://en.cppreference.com/w/cpp/container/set
| int res = ::epoll_ctl(m_epoll_fd, EPOLL_CTL_DEL, fd, NULL); | ||
| if (res == -1) | ||
| { | ||
| std::string error = std::string("Select::del_fd:epoll_ctl: error=(" |
There was a problem hiding this comment.
std:: [](start = 8, length = 5)
No need to add namespace #Pending
There was a problem hiding this comment.
I'm used to use prefixes to avoid ambiguity when reading.
string is so common name, so std::string looks much better.
Anyway we have ~800 usage of std in swss-common
$ grep 'std::' * | wc -l
804
common/select.cpp
Outdated
|
|
||
| /* Checking caching from reader */ | ||
| for (Selectable *i : m_objects) | ||
| while (!m_ready.empty()) |
There was a problem hiding this comment.
while [](start = 4, length = 5)
Since you return in the block, why not use 'if'? #Closed
common/select.cpp
Outdated
| timeout = -1; | ||
|
|
||
| /* check if we have some data */ | ||
| ret = select1(c, 0); |
There was a problem hiding this comment.
select1 [](start = 10, length = 7)
select1 is a weird name. #Closed
If we have selectables with equal priority, select will choose a selectable which was chosen before all others. So one selectable can't block others This commit also contains typo fix
This reverts commit bac891b.
|
Current master has broken unit tests. As soon as they are fixed, I'll resolve conflicts and make some requested changes. |
|
resolve conflict first? |
|
I've resolved the conflicts, but I have to check everything, until I'm sure everything is alright. |
|
retest this please |
|
All tests are done. The PR is ready for the final review |
common/selectable.h
Outdated
|
|
||
| /* if the priorities are equal */ | ||
| /* use Selectable which was selected later */ | ||
| if (a->getLastTimeUsed() < b->getLastTimeUsed()) |
There was a problem hiding this comment.
getLastTimeUsed [](start = 19, length = 15)
The order is dynamic, I am afraid it will break the assumption of std::set
…l object, to avoid it using by others
|
Qi, I share your concern about the Comparator using the mutable state. But in this case I don't have any other simple solution. So what I did:
Also I have a comment about danger of using Selectalbe->updateLastUsedTime() on the Selectable which is inside of the set. |
qiluo-msft
left a comment
There was a problem hiding this comment.
I have no more comments. Please check with other reviewers.
PLEASE DON'T PUSH THIS CHANGE. IT'LL BREAK BOTH SWSS AND SAIREDIS.
This refactoring introduce support of priorities for Selectables. Selectables with highest priorities will be selected first. If we have two selectables with the same priorities, the selectable which was accessed earliest will be chosen.
The priorities are defined as last argument of type int for following classes:
To support this feature Selectable interface was changed significantly.
Now Selectable has to provide following methods:
The method Select::select() was changed. int fd parameter was remove as not used anywhere*
I switched from Unix select() to Linux epoll which is more effective and easy to use.
Also I found that SelectableTimer could lose it's events, if reading rate is greater then timer interval. Probably it's a bug.
Also I made some other small changes and tweaks to improve performance of the swss-common. I'm going to create a separate PR with more performance changes for swss-common.