Skip to content

Commit 256e402

Browse files
nguydavizulinx86
authored andcommitted
perf: Change virtio event_handlers to use Events::with_data()
Using Events::with_data when registering events for block/network/vsock devices and associating a u32 const data with each event. Then, in the process function, instead of using if to see what process_* function to call, we can do a match on consecutive u32 values which is going to be optimized by the compiler into a jump table. Signed-off-by: David Nguyen <nguydavi@amazon.com>
1 parent 75e7c65 commit 256e402

File tree

6 files changed

+212
-112
lines changed

6 files changed

+212
-112
lines changed

src/vmm/src/devices/virtio/balloon/event_handler.rs

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use std::os::unix::io::AsRawFd;
5-
64
use event_manager::{EventOps, Events, MutEventSubscriber};
75
use utils::epoll::EventSet;
86

@@ -12,25 +10,51 @@ use crate::devices::virtio::device::VirtioDevice;
1210
use crate::logger::{error, warn};
1311

1412
impl Balloon {
13+
const PROCESS_ACTIVATE: u32 = 0;
14+
const PROCESS_VIRTQ_INFLATE: u32 = 1;
15+
const PROCESS_VIRTQ_DEFLATE: u32 = 2;
16+
const PROCESS_VIRTQ_STATS: u32 = 3;
17+
const PROCESS_STATS_TIMER: u32 = 4;
18+
1519
fn register_runtime_events(&self, ops: &mut EventOps) {
16-
if let Err(err) = ops.add(Events::new(&self.queue_evts[INFLATE_INDEX], EventSet::IN)) {
20+
if let Err(err) = ops.add(Events::with_data(
21+
&self.queue_evts[INFLATE_INDEX],
22+
Self::PROCESS_VIRTQ_INFLATE,
23+
EventSet::IN,
24+
)) {
1725
error!("Failed to register inflate queue event: {}", err);
1826
}
19-
if let Err(err) = ops.add(Events::new(&self.queue_evts[DEFLATE_INDEX], EventSet::IN)) {
27+
if let Err(err) = ops.add(Events::with_data(
28+
&self.queue_evts[DEFLATE_INDEX],
29+
Self::PROCESS_VIRTQ_DEFLATE,
30+
EventSet::IN,
31+
)) {
2032
error!("Failed to register deflate queue event: {}", err);
2133
}
2234
if self.stats_enabled() {
23-
if let Err(err) = ops.add(Events::new(&self.queue_evts[STATS_INDEX], EventSet::IN)) {
35+
if let Err(err) = ops.add(Events::with_data(
36+
&self.queue_evts[STATS_INDEX],
37+
Self::PROCESS_VIRTQ_STATS,
38+
EventSet::IN,
39+
)) {
2440
error!("Failed to register stats queue event: {}", err);
2541
}
26-
if let Err(err) = ops.add(Events::new(&self.stats_timer, EventSet::IN)) {
42+
if let Err(err) = ops.add(Events::with_data(
43+
&self.stats_timer,
44+
Self::PROCESS_STATS_TIMER,
45+
EventSet::IN,
46+
)) {
2747
error!("Failed to register stats timerfd event: {}", err);
2848
}
2949
}
3050
}
3151

3252
fn register_activate_event(&self, ops: &mut EventOps) {
33-
if let Err(err) = ops.add(Events::new(&self.activate_evt, EventSet::IN)) {
53+
if let Err(err) = ops.add(Events::with_data(
54+
&self.activate_evt,
55+
Self::PROCESS_ACTIVATE,
56+
EventSet::IN,
57+
)) {
3458
error!("Failed to register activate event: {}", err);
3559
}
3660
}
@@ -40,15 +64,19 @@ impl Balloon {
4064
error!("Failed to consume balloon activate event: {:?}", err);
4165
}
4266
self.register_runtime_events(ops);
43-
if let Err(err) = ops.remove(Events::new(&self.activate_evt, EventSet::IN)) {
67+
if let Err(err) = ops.remove(Events::with_data(
68+
&self.activate_evt,
69+
Self::PROCESS_ACTIVATE,
70+
EventSet::IN,
71+
)) {
4472
error!("Failed to un-register activate event: {}", err);
4573
}
4674
}
4775
}
4876

4977
impl MutEventSubscriber for Balloon {
5078
fn process(&mut self, event: Events, ops: &mut EventOps) {
51-
let source = event.fd();
79+
let source = event.data();
5280
let event_set = event.event_set();
5381
let supported_events = EventSet::IN;
5482

@@ -61,27 +89,20 @@ impl MutEventSubscriber for Balloon {
6189
}
6290

6391
if self.is_activated() {
64-
let virtq_inflate_ev_fd = self.queue_evts[INFLATE_INDEX].as_raw_fd();
65-
let virtq_deflate_ev_fd = self.queue_evts[DEFLATE_INDEX].as_raw_fd();
66-
let virtq_stats_ev_fd = self.queue_evts[STATS_INDEX].as_raw_fd();
67-
let stats_timer_fd = self.stats_timer.as_raw_fd();
68-
let activate_fd = self.activate_evt.as_raw_fd();
69-
70-
// Looks better than C style if/else if/else.
7192
match source {
72-
_ if source == virtq_inflate_ev_fd => self
93+
Self::PROCESS_ACTIVATE => self.process_activate_event(ops),
94+
Self::PROCESS_VIRTQ_INFLATE => self
7395
.process_inflate_queue_event()
7496
.unwrap_or_else(report_balloon_event_fail),
75-
_ if source == virtq_deflate_ev_fd => self
97+
Self::PROCESS_VIRTQ_DEFLATE => self
7698
.process_deflate_queue_event()
7799
.unwrap_or_else(report_balloon_event_fail),
78-
_ if source == virtq_stats_ev_fd => self
100+
Self::PROCESS_VIRTQ_STATS => self
79101
.process_stats_queue_event()
80102
.unwrap_or_else(report_balloon_event_fail),
81-
_ if source == stats_timer_fd => self
103+
Self::PROCESS_STATS_TIMER => self
82104
.process_stats_timer_event()
83105
.unwrap_or_else(report_balloon_event_fail),
84-
_ if activate_fd == source => self.process_activate_event(ops),
85106
_ => {
86107
warn!("Balloon: Spurious event received: {:?}", source);
87108
}

src/vmm/src/devices/virtio/net/event_handler.rs

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use std::os::unix::io::AsRawFd;
5-
64
use event_manager::{EventOps, Events, MutEventSubscriber};
75
use utils::epoll::EventSet;
86

@@ -12,29 +10,57 @@ use crate::devices::virtio::net::{RX_INDEX, TX_INDEX};
1210
use crate::logger::{error, warn, IncMetric};
1311

1412
impl Net {
13+
const PROCESS_ACTIVATE: u32 = 0;
14+
const PROCESS_VIRTQ_RX: u32 = 1;
15+
const PROCESS_VIRTQ_TX: u32 = 2;
16+
const PROCESS_TAP_RX: u32 = 3;
17+
const PROCESS_RX_RATE_LIMITER: u32 = 4;
18+
const PROCESS_TX_RATE_LIMITER: u32 = 5;
19+
1520
fn register_runtime_events(&self, ops: &mut EventOps) {
16-
if let Err(err) = ops.add(Events::new(&self.queue_evts[RX_INDEX], EventSet::IN)) {
21+
if let Err(err) = ops.add(Events::with_data(
22+
&self.queue_evts[RX_INDEX],
23+
Self::PROCESS_VIRTQ_RX,
24+
EventSet::IN,
25+
)) {
1726
error!("Failed to register rx queue event: {}", err);
1827
}
19-
if let Err(err) = ops.add(Events::new(&self.queue_evts[TX_INDEX], EventSet::IN)) {
28+
if let Err(err) = ops.add(Events::with_data(
29+
&self.queue_evts[TX_INDEX],
30+
Self::PROCESS_VIRTQ_TX,
31+
EventSet::IN,
32+
)) {
2033
error!("Failed to register tx queue event: {}", err);
2134
}
22-
if let Err(err) = ops.add(Events::new(&self.rx_rate_limiter, EventSet::IN)) {
35+
if let Err(err) = ops.add(Events::with_data(
36+
&self.rx_rate_limiter,
37+
Self::PROCESS_RX_RATE_LIMITER,
38+
EventSet::IN,
39+
)) {
2340
error!("Failed to register rx queue event: {}", err);
2441
}
25-
if let Err(err) = ops.add(Events::new(&self.tx_rate_limiter, EventSet::IN)) {
42+
if let Err(err) = ops.add(Events::with_data(
43+
&self.tx_rate_limiter,
44+
Self::PROCESS_TX_RATE_LIMITER,
45+
EventSet::IN,
46+
)) {
2647
error!("Failed to register tx queue event: {}", err);
2748
}
28-
if let Err(err) = ops.add(Events::new(
49+
if let Err(err) = ops.add(Events::with_data(
2950
&self.tap,
51+
Self::PROCESS_TAP_RX,
3052
EventSet::IN | EventSet::EDGE_TRIGGERED,
3153
)) {
3254
error!("Failed to register tap event: {}", err);
3355
}
3456
}
3557

3658
fn register_activate_event(&self, ops: &mut EventOps) {
37-
if let Err(err) = ops.add(Events::new(&self.activate_evt, EventSet::IN)) {
59+
if let Err(err) = ops.add(Events::with_data(
60+
&self.activate_evt,
61+
Self::PROCESS_ACTIVATE,
62+
EventSet::IN,
63+
)) {
3864
error!("Failed to register activate event: {}", err);
3965
}
4066
}
@@ -44,15 +70,19 @@ impl Net {
4470
error!("Failed to consume net activate event: {:?}", err);
4571
}
4672
self.register_runtime_events(ops);
47-
if let Err(err) = ops.remove(Events::new(&self.activate_evt, EventSet::IN)) {
73+
if let Err(err) = ops.remove(Events::with_data(
74+
&self.activate_evt,
75+
Self::PROCESS_ACTIVATE,
76+
EventSet::IN,
77+
)) {
4878
error!("Failed to un-register activate event: {}", err);
4979
}
5080
}
5181
}
5282

5383
impl MutEventSubscriber for Net {
5484
fn process(&mut self, event: Events, ops: &mut EventOps) {
55-
let source = event.fd();
85+
let source = event.data();
5686
let event_set = event.event_set();
5787

5888
// TODO: also check for errors. Pending high level discussions on how we want
@@ -67,21 +97,13 @@ impl MutEventSubscriber for Net {
6797
}
6898

6999
if self.is_activated() {
70-
let virtq_rx_ev_fd = self.queue_evts[RX_INDEX].as_raw_fd();
71-
let virtq_tx_ev_fd = self.queue_evts[TX_INDEX].as_raw_fd();
72-
let rx_rate_limiter_fd = self.rx_rate_limiter.as_raw_fd();
73-
let tx_rate_limiter_fd = self.tx_rate_limiter.as_raw_fd();
74-
let tap_fd = self.tap.as_raw_fd();
75-
let activate_fd = self.activate_evt.as_raw_fd();
76-
77-
// Looks better than C style if/else if/else.
78100
match source {
79-
_ if source == virtq_rx_ev_fd => self.process_rx_queue_event(),
80-
_ if source == tap_fd => self.process_tap_rx_event(),
81-
_ if source == virtq_tx_ev_fd => self.process_tx_queue_event(),
82-
_ if source == rx_rate_limiter_fd => self.process_rx_rate_limiter_event(),
83-
_ if source == tx_rate_limiter_fd => self.process_tx_rate_limiter_event(),
84-
_ if activate_fd == source => self.process_activate_event(ops),
101+
Self::PROCESS_ACTIVATE => self.process_activate_event(ops),
102+
Self::PROCESS_VIRTQ_RX => self.process_rx_queue_event(),
103+
Self::PROCESS_VIRTQ_TX => self.process_tx_queue_event(),
104+
Self::PROCESS_TAP_RX => self.process_tap_rx_event(),
105+
Self::PROCESS_RX_RATE_LIMITER => self.process_rx_rate_limiter_event(),
106+
Self::PROCESS_TX_RATE_LIMITER => self.process_tx_rate_limiter_event(),
85107
_ => {
86108
warn!("Net: Spurious event received: {:?}", source);
87109
self.metrics.event_fails.inc();

src/vmm/src/devices/virtio/rng/event_handler.rs

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
use std::os::unix::io::AsRawFd;
5-
64
use event_manager::{EventOps, Events, MutEventSubscriber};
75
use utils::epoll::EventSet;
86

@@ -11,17 +9,33 @@ use crate::devices::virtio::device::VirtioDevice;
119
use crate::logger::{error, warn};
1210

1311
impl Entropy {
12+
const PROCESS_ACTIVATE: u32 = 0;
13+
const PROCESS_ENTROPY_QUEUE: u32 = 1;
14+
const PROCESS_RATE_LIMITER: u32 = 2;
15+
1416
fn register_runtime_events(&self, ops: &mut EventOps) {
15-
if let Err(err) = ops.add(Events::new(&self.queue_events()[RNG_QUEUE], EventSet::IN)) {
17+
if let Err(err) = ops.add(Events::with_data(
18+
&self.queue_events()[RNG_QUEUE],
19+
Self::PROCESS_ENTROPY_QUEUE,
20+
EventSet::IN,
21+
)) {
1622
error!("entropy: Failed to register queue event: {err}");
1723
}
18-
if let Err(err) = ops.add(Events::new(self.rate_limiter(), EventSet::IN)) {
24+
if let Err(err) = ops.add(Events::with_data(
25+
self.rate_limiter(),
26+
Self::PROCESS_RATE_LIMITER,
27+
EventSet::IN,
28+
)) {
1929
error!("entropy: Failed to register rate-limiter event: {err}");
2030
}
2131
}
2232

2333
fn register_activate_event(&self, ops: &mut EventOps) {
24-
if let Err(err) = ops.add(Events::new(self.activate_event(), EventSet::IN)) {
34+
if let Err(err) = ops.add(Events::with_data(
35+
self.activate_event(),
36+
Self::PROCESS_ACTIVATE,
37+
EventSet::IN,
38+
)) {
2539
error!("entropy: Failed to register activate event: {err}");
2640
}
2741
}
@@ -35,7 +49,11 @@ impl Entropy {
3549
self.register_runtime_events(ops);
3650

3751
// Remove activate event
38-
if let Err(err) = ops.remove(Events::new(self.activate_event(), EventSet::IN)) {
52+
if let Err(err) = ops.remove(Events::with_data(
53+
self.activate_event(),
54+
Self::PROCESS_ACTIVATE,
55+
EventSet::IN,
56+
)) {
3957
error!("entropy: Failed to un-register activate event: {err}");
4058
}
4159
}
@@ -56,7 +74,7 @@ impl MutEventSubscriber for Entropy {
5674

5775
fn process(&mut self, events: event_manager::Events, ops: &mut event_manager::EventOps) {
5876
let event_set = events.event_set();
59-
let source = events.fd();
77+
let source = events.data();
6078

6179
if !event_set.contains(EventSet::IN) {
6280
warn!("entropy: Received unknown event: {event_set:?} from source {source}");
@@ -68,14 +86,13 @@ impl MutEventSubscriber for Entropy {
6886
return;
6987
}
7088

71-
if source == self.queue_events()[RNG_QUEUE].as_raw_fd() {
72-
self.process_entropy_queue_event()
73-
} else if source == self.rate_limiter().as_raw_fd() {
74-
self.process_rate_limiter_event();
75-
} else if source == self.activate_event().as_raw_fd() {
76-
self.process_activate_event(ops)
77-
} else {
78-
warn!("entropy: Unknown event received: {source}");
89+
match source {
90+
Self::PROCESS_ACTIVATE => self.process_activate_event(ops),
91+
Self::PROCESS_ENTROPY_QUEUE => self.process_entropy_queue_event(),
92+
Self::PROCESS_RATE_LIMITER => self.process_rate_limiter_event(),
93+
_ => {
94+
warn!("entropy: Unknown event received: {source}");
95+
}
7996
}
8097
}
8198
}

src/vmm/src/devices/virtio/vhost_user_block/event_handler.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
// Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
3-
4-
use std::os::fd::AsRawFd;
5-
63
use event_manager::{EventOps, Events, MutEventSubscriber};
74
use utils::epoll::EventSet;
85

@@ -11,8 +8,14 @@ use crate::devices::virtio::device::VirtioDevice;
118
use crate::logger::{error, warn};
129

1310
impl VhostUserBlock {
11+
const PROCESS_ACTIVATE: u32 = 0;
12+
1413
fn register_activate_event(&self, ops: &mut EventOps) {
15-
if let Err(err) = ops.add(Events::new(&self.activate_evt, EventSet::IN)) {
14+
if let Err(err) = ops.add(Events::with_data(
15+
&self.activate_evt,
16+
Self::PROCESS_ACTIVATE,
17+
EventSet::IN,
18+
)) {
1619
error!("Failed to register activate event: {}", err);
1720
}
1821
}
@@ -21,7 +24,11 @@ impl VhostUserBlock {
2124
if let Err(err) = self.activate_evt.read() {
2225
error!("Failed to consume block activate event: {:?}", err);
2326
}
24-
if let Err(err) = ops.remove(Events::new(&self.activate_evt, EventSet::IN)) {
27+
if let Err(err) = ops.remove(Events::with_data(
28+
&self.activate_evt,
29+
Self::PROCESS_ACTIVATE,
30+
EventSet::IN,
31+
)) {
2532
error!("Failed to un-register activate event: {}", err);
2633
}
2734
}
@@ -30,7 +37,7 @@ impl VhostUserBlock {
3037
impl MutEventSubscriber for VhostUserBlock {
3138
// Handle an event for queue or rate limiter.
3239
fn process(&mut self, event: Events, ops: &mut EventOps) {
33-
let source = event.fd();
40+
let source = event.data();
3441
let event_set = event.event_set();
3542
let supported_events = EventSet::IN;
3643

@@ -43,8 +50,7 @@ impl MutEventSubscriber for VhostUserBlock {
4350
}
4451

4552
if self.is_activated() {
46-
let activate_fd = self.activate_evt.as_raw_fd();
47-
if activate_fd == source {
53+
if Self::PROCESS_ACTIVATE == source {
4854
self.process_activate_event(ops)
4955
} else {
5056
warn!("BlockVhost: Spurious event received: {:?}", source)

0 commit comments

Comments
 (0)