Skip to content

Commit 551a0c7

Browse files
committed
Attempt to improve performance of event loop in offline rendering
- inline some methods - only conditionally poll for control messages
1 parent 663b8ae commit 551a0c7

File tree

2 files changed

+120
-103
lines changed

2 files changed

+120
-103
lines changed

src/events.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,15 @@ impl EventLoop {
166166
result
167167
}
168168

169-
pub fn handle_pending_events(&self) {
169+
#[inline(always)]
170+
pub fn handle_pending_events(&self) -> bool {
171+
let mut events_were_handled = false;
170172
// try_iter will yield all pending events, but does not block
171173
for event in self.event_recv.try_iter() {
172174
self.handle_event(event);
175+
events_were_handled = true;
173176
}
177+
events_were_handled
174178
}
175179

176180
pub fn run_in_thread(&self) {

src/render/thread.rs

Lines changed: 115 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use std::any::Any;
44
use std::cell::Cell;
5-
5+
use std::ops::ControlFlow;
66
use std::sync::atomic::{AtomicU64, AtomicU8, Ordering};
77
use std::sync::Arc;
88
use std::time::{Duration, Instant};
@@ -105,116 +105,125 @@ impl RenderThread {
105105
}
106106
}
107107

108+
#[inline(always)]
108109
fn handle_control_messages(&mut self) {
109-
let receiver = match &self.receiver {
110-
None => return,
111-
Some(receiver) => receiver,
112-
};
110+
if self.receiver.is_none() {
111+
return;
112+
}
113113

114-
for msg in receiver.try_iter() {
115-
use ControlMessage::*;
114+
while let Ok(msg) = self.receiver.as_ref().unwrap().try_recv() {
115+
let result = self.handle_control_message(msg);
116+
if result.is_break() {
117+
return; // stop processing
118+
}
119+
}
120+
}
116121

117-
match msg {
118-
RegisterNode {
119-
id: node_id,
122+
fn handle_control_message(&mut self, msg: ControlMessage) -> ControlFlow<()> {
123+
use ControlMessage::*;
124+
125+
match msg {
126+
RegisterNode {
127+
id: node_id,
128+
reclaim_id,
129+
node,
130+
inputs,
131+
outputs,
132+
channel_config,
133+
} => {
134+
self.graph.as_mut().unwrap().add_node(
135+
node_id,
120136
reclaim_id,
121137
node,
122138
inputs,
123139
outputs,
124140
channel_config,
125-
} => {
126-
self.graph.as_mut().unwrap().add_node(
127-
node_id,
128-
reclaim_id,
129-
node,
130-
inputs,
131-
outputs,
132-
channel_config,
133-
);
134-
}
135-
ConnectNode {
136-
from,
137-
to,
138-
output,
139-
input,
140-
} => {
141-
self.graph
142-
.as_mut()
143-
.unwrap()
144-
.add_edge((from, output), (to, input));
145-
}
146-
DisconnectNode { from, to } => {
147-
self.graph.as_mut().unwrap().remove_edge(from, to);
148-
}
149-
DisconnectAll { from } => {
150-
self.graph.as_mut().unwrap().remove_edges_from(from);
151-
}
152-
ControlHandleDropped { id } => {
153-
self.graph.as_mut().unwrap().mark_control_handle_dropped(id);
154-
}
155-
MarkCycleBreaker { id } => {
156-
self.graph.as_mut().unwrap().mark_cycle_breaker(id);
157-
}
158-
CloseAndRecycle { sender } => {
159-
self.set_state(AudioContextState::Suspended);
160-
let _ = sender.send(self.graph.take().unwrap());
161-
self.receiver = None;
162-
return; // no further handling of ctrl msgs
163-
}
164-
Startup { graph } => {
165-
debug_assert!(self.graph.is_none());
166-
self.graph = Some(graph);
167-
self.set_state(AudioContextState::Running);
168-
}
169-
NodeMessage { id, mut msg } => {
170-
self.graph.as_mut().unwrap().route_message(id, msg.as_mut());
171-
if let Some(gc) = self.garbage_collector.as_mut() {
172-
gc.push(msg)
173-
}
174-
}
175-
RunDiagnostics { mut buffer } => {
176-
use std::io::Write;
177-
writeln!(&mut buffer, "{:#?}", &self).ok();
178-
writeln!(&mut buffer, "{:?}", &self.graph).ok();
179-
self.event_sender
180-
.try_send(EventDispatch::diagnostics(buffer))
181-
.expect("Unable to send diagnostics - channel is full");
182-
}
183-
Suspend { notify } => {
184-
self.suspended = true;
185-
self.set_state(AudioContextState::Suspended);
186-
notify.send();
187-
}
188-
Resume { notify } => {
189-
self.suspended = false;
190-
self.set_state(AudioContextState::Running);
191-
notify.send();
192-
}
193-
Close { notify } => {
194-
self.suspended = true;
195-
self.set_state(AudioContextState::Closed);
196-
notify.send();
141+
);
142+
}
143+
ConnectNode {
144+
from,
145+
to,
146+
output,
147+
input,
148+
} => {
149+
self.graph
150+
.as_mut()
151+
.unwrap()
152+
.add_edge((from, output), (to, input));
153+
}
154+
DisconnectNode { from, to } => {
155+
self.graph.as_mut().unwrap().remove_edge(from, to);
156+
}
157+
DisconnectAll { from } => {
158+
self.graph.as_mut().unwrap().remove_edges_from(from);
159+
}
160+
ControlHandleDropped { id } => {
161+
self.graph.as_mut().unwrap().mark_control_handle_dropped(id);
162+
}
163+
MarkCycleBreaker { id } => {
164+
self.graph.as_mut().unwrap().mark_cycle_breaker(id);
165+
}
166+
CloseAndRecycle { sender } => {
167+
self.set_state(AudioContextState::Suspended);
168+
let _ = sender.send(self.graph.take().unwrap());
169+
self.receiver = None;
170+
return ControlFlow::Break(()); // no further handling of ctrl msgs
171+
}
172+
Startup { graph } => {
173+
debug_assert!(self.graph.is_none());
174+
self.graph = Some(graph);
175+
self.set_state(AudioContextState::Running);
176+
}
177+
NodeMessage { id, mut msg } => {
178+
self.graph.as_mut().unwrap().route_message(id, msg.as_mut());
179+
if let Some(gc) = self.garbage_collector.as_mut() {
180+
gc.push(msg)
197181
}
182+
}
183+
RunDiagnostics { mut buffer } => {
184+
use std::io::Write;
185+
writeln!(&mut buffer, "{:#?}", &self).ok();
186+
writeln!(&mut buffer, "{:?}", &self.graph).ok();
187+
self.event_sender
188+
.try_send(EventDispatch::diagnostics(buffer))
189+
.expect("Unable to send diagnostics - channel is full");
190+
}
191+
Suspend { notify } => {
192+
self.suspended = true;
193+
self.set_state(AudioContextState::Suspended);
194+
notify.send();
195+
}
196+
Resume { notify } => {
197+
self.suspended = false;
198+
self.set_state(AudioContextState::Running);
199+
notify.send();
200+
}
201+
Close { notify } => {
202+
self.suspended = true;
203+
self.set_state(AudioContextState::Closed);
204+
notify.send();
205+
}
198206

199-
SetChannelCount { id, count } => {
200-
self.graph.as_mut().unwrap().set_channel_count(id, count);
201-
}
207+
SetChannelCount { id, count } => {
208+
self.graph.as_mut().unwrap().set_channel_count(id, count);
209+
}
202210

203-
SetChannelCountMode { id, mode } => {
204-
self.graph
205-
.as_mut()
206-
.unwrap()
207-
.set_channel_count_mode(id, mode);
208-
}
211+
SetChannelCountMode { id, mode } => {
212+
self.graph
213+
.as_mut()
214+
.unwrap()
215+
.set_channel_count_mode(id, mode);
216+
}
209217

210-
SetChannelInterpretation { id, interpretation } => {
211-
self.graph
212-
.as_mut()
213-
.unwrap()
214-
.set_channel_interpretation(id, interpretation);
215-
}
218+
SetChannelInterpretation { id, interpretation } => {
219+
self.graph
220+
.as_mut()
221+
.unwrap()
222+
.set_channel_interpretation(id, interpretation);
216223
}
217224
}
225+
226+
ControlFlow::Continue(()) // continue handling more messages
218227
}
219228

220229
// Render method of the `OfflineAudioContext::start_rendering_sync`
@@ -240,22 +249,26 @@ impl RenderThread {
240249
let mut buffer = AudioBuffer::new(options);
241250
let num_frames = (length + RENDER_QUANTUM_SIZE - 1) / RENDER_QUANTUM_SIZE;
242251

243-
// Handle addition/removal of nodes/edges
252+
// Handle initial control messages
244253
self.handle_control_messages();
245254

246255
for quantum in 0..num_frames {
247256
// Suspend at given times and run callbacks
248257
if suspend_callbacks.first().map(|&(q, _)| q) == Some(quantum) {
249258
let callback = suspend_callbacks.remove(0).1;
250259
(callback)(context);
251-
}
252260

253-
// Handle addition/removal of nodes/edges
254-
self.handle_control_messages();
261+
// Handle any control messages that may have been submitted by the callback
262+
self.handle_control_messages();
263+
}
255264

256265
self.render_offline_quantum(&mut buffer);
257266

258-
event_loop.handle_pending_events();
267+
let events_were_handled = event_loop.handle_pending_events();
268+
if events_were_handled {
269+
// Handle any control messages that may have been submitted by the handler
270+
self.handle_control_messages();
271+
}
259272
}
260273

261274
buffer

0 commit comments

Comments
 (0)