Based on this medium post

Long story short, when you use epoll, the kernel keeps relevant data in the kernel space, monitors files in the interest list behind the scene and sends back only a short list of ready descriptors. On the contrary, poll/select is more like an on-demand service, remembers nothing and returns everything, which means that you will have to pass everything to the kernel every time, wait until the kernel is done polling, get back a long list of all the descriptors you just sent and loop through the long list yourself to find out what’s up.

More details can be found here.