Skip to content
Snippets Groups Projects
Commit d11a6daa authored by Avi Kivity's avatar Avi Kivity
Browse files

vring: avoid expensive divides


Replace divides by variables and by the hard constants with masks and
divides by easy constants.

Improves netperf by about 1.6%.

Noted by Vlad.

Reviewed-by: default avatarDor Laor <dor@cloudius-systems.com>
Reviewed-by: default avatarAsias He <asias@cloudius-systems.com>
Signed-off-by: default avatarAvi Kivity <avi@cloudius-systems.com>
parent 53c1632c
No related branches found
No related tags found
No related merge requests found
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "sched.hh" #include "sched.hh"
#include "interrupt.hh" #include "interrupt.hh"
#include "osv/trace.hh" #include "osv/trace.hh"
#include <ilog2.hh>
using namespace memory; using namespace memory;
using sched::thread; using sched::thread;
...@@ -36,6 +37,7 @@ namespace virtio { ...@@ -36,6 +37,7 @@ namespace virtio {
memset(_vring_ptr, 0, sz); memset(_vring_ptr, 0, sz);
// Set up pointers // Set up pointers
assert(is_power_of_two(num));
_num = num; _num = num;
_desc = (vring_desc *)_vring_ptr; _desc = (vring_desc *)_vring_ptr;
_avail = (vring_avail *)(_vring_ptr + num*sizeof(vring_desc)); _avail = (vring_avail *)(_vring_ptr + num*sizeof(vring_desc));
...@@ -89,7 +91,7 @@ namespace virtio { ...@@ -89,7 +91,7 @@ namespace virtio {
return false && // It degrades netperf performance return false && // It degrades netperf performance
_dev->get_indirect_buf_cap() && _dev->get_indirect_buf_cap() &&
desc_needed > 1 && // no need to use indirect for a single descriptor desc_needed > 1 && // no need to use indirect for a single descriptor
_avail_count < _num / 3; // use indirect only when low space _avail_count < _num / 4; // use indirect only when low space
} }
void vring::enable_interrupts() void vring::enable_interrupts()
...@@ -156,7 +158,7 @@ namespace virtio { ...@@ -156,7 +158,7 @@ namespace virtio {
_avail_count -= desc_needed; _avail_count -= desc_needed;
u16 avail_idx_cache = _avail->_idx.load(std::memory_order_relaxed); u16 avail_idx_cache = _avail->_idx.load(std::memory_order_relaxed);
_avail->_ring[avail_idx_cache % _num] = _avail_head; _avail->_ring[avail_idx_cache & (_num - 1)] = _avail_head;
//Cheaper than the operator++ that uses seq consistency //Cheaper than the operator++ that uses seq consistency
_avail->_idx.store(avail_idx_cache + 1, std::memory_order_release); _avail->_idx.store(avail_idx_cache + 1, std::memory_order_release);
_avail_head = idx; _avail_head = idx;
...@@ -174,7 +176,7 @@ namespace virtio { ...@@ -174,7 +176,7 @@ namespace virtio {
int i = 1; int i = 1;
// need to trim the free running counter w/ the array size // need to trim the free running counter w/ the array size
int used_ptr = _used_ring_guest_head % _num; int used_ptr = _used_ring_guest_head & (_num - 1);
elem = _used->_used_elements[used_ptr]; elem = _used->_used_elements[used_ptr];
int idx = elem._id; int idx = elem._id;
...@@ -202,7 +204,7 @@ namespace virtio { ...@@ -202,7 +204,7 @@ namespace virtio {
void* cookie = nullptr; void* cookie = nullptr;
// need to trim the free running counter w/ the array size // need to trim the free running counter w/ the array size
int used_ptr = _used_ring_host_head % _num; int used_ptr = _used_ring_host_head & (_num - 1);
if (_used_ring_host_head == _used->_idx.load(std::memory_order_acquire)) { if (_used_ring_host_head == _used->_idx.load(std::memory_order_acquire)) {
return nullptr; return nullptr;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment