Revert of Avoid calling PostTask in audio callbacks (patchset #6 id:100001 of https://codereview.webrtc.org/2663383004/ )
Reason for revert:
Speculative revert to see if this CL caused a change in performance tests.
See https://bugs.chromium.org/p/chromium/issues/detail?id=689919 for details.
Original issue's description:
> Avoid calling PostTask in audio callbacks.
>
> We have seen that PostTask can consume some CPU and the way we used it
> before (logging only) in the ADB is not worth the cost we see when
> profiling.
>
> This CL simply moves frequent (trivial) stat updates from the task queue
> to the native threads to avoid calling PostTask in each callback.
> The reason for doing so before was to avoid locks but we can live without
> them since races are benign here.
>
>
> BUG=webrtc:7096
>
> Review-Url: https://codereview.webrtc.org/2663383004
> Cr-Commit-Position: refs/heads/master@{#16429}
> Committed: 77ce9a5541
TBR=solenberg@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=webrtc:7096
Review-Url: https://codereview.webrtc.org/2684913003
Cr-Commit-Position: refs/heads/master@{#16490}
This commit is contained in:
parent
219208991b
commit
fd8f102a84
@ -53,10 +53,21 @@ AudioDeviceBuffer::AudioDeviceBuffer()
|
||||
rec_delay_ms_(0),
|
||||
clock_drift_(0),
|
||||
num_stat_reports_(0),
|
||||
rec_callbacks_(0),
|
||||
last_rec_callbacks_(0),
|
||||
play_callbacks_(0),
|
||||
last_play_callbacks_(0),
|
||||
rec_samples_(0),
|
||||
last_rec_samples_(0),
|
||||
play_samples_(0),
|
||||
last_play_samples_(0),
|
||||
max_rec_level_(0),
|
||||
max_play_level_(0),
|
||||
last_timer_task_time_(0),
|
||||
rec_stat_count_(0),
|
||||
play_stat_count_(0),
|
||||
play_start_time_(0),
|
||||
rec_start_time_(0),
|
||||
only_silence_recorded_(true),
|
||||
log_stats_(false) {
|
||||
LOG(INFO) << "AudioDeviceBuffer::ctor";
|
||||
@ -315,9 +326,13 @@ int32_t AudioDeviceBuffer::SetRecordedBuffer(const void* audio_buffer,
|
||||
only_silence_recorded_ = false;
|
||||
}
|
||||
}
|
||||
// Update recording stats which is used as base for periodic logging of the
|
||||
// audio input state.
|
||||
UpdateRecStats(max_abs, samples_per_channel);
|
||||
// Update some stats but do it on the task queue to ensure that the members
|
||||
// are modified and read on the same thread. Note that |max_abs| will be
|
||||
// zero in most calls and then have no effect of the stats. It is only updated
|
||||
// approximately two times per second and can then change the stats.
|
||||
task_queue_.PostTask([this, max_abs, samples_per_channel] {
|
||||
UpdateRecStats(max_abs, samples_per_channel);
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -382,9 +397,13 @@ int32_t AudioDeviceBuffer::RequestPlayoutData(size_t samples_per_channel) {
|
||||
WebRtcSpl_MaxAbsValueW16(play_buffer_.data(), play_buffer_.size());
|
||||
play_stat_count_ = 0;
|
||||
}
|
||||
// Update playout stats which is used as base for periodic logging of the
|
||||
// audio output state.
|
||||
UpdatePlayStats(max_abs, num_samples_out);
|
||||
// Update some stats but do it on the task queue to ensure that the members
|
||||
// are modified and read on the same thread. Note that |max_abs| will be
|
||||
// zero in most calls and then have no effect of the stats. It is only updated
|
||||
// approximately two times per second and can then change the stats.
|
||||
task_queue_.PostTask([this, max_abs, num_samples_out] {
|
||||
UpdatePlayStats(max_abs, num_samples_out);
|
||||
});
|
||||
return static_cast<int32_t>(num_samples_out);
|
||||
}
|
||||
|
||||
@ -434,37 +453,37 @@ void AudioDeviceBuffer::LogStats(LogState state) {
|
||||
int64_t time_since_last = rtc::TimeDiff(now_time, last_timer_task_time_);
|
||||
last_timer_task_time_ = now_time;
|
||||
|
||||
Stats stats;
|
||||
{
|
||||
rtc::CritScope cs(&lock_);
|
||||
stats = stats_;
|
||||
stats_.max_rec_level = 0;
|
||||
stats_.max_play_level = 0;
|
||||
}
|
||||
|
||||
// Log the latest statistics but skip the first round just after state was
|
||||
// set to LOG_START. Hence, first printed log will be after ~10 seconds.
|
||||
if (++num_stat_reports_ > 1 && time_since_last > 0) {
|
||||
uint32_t diff_samples = stats.rec_samples - last_stats_.rec_samples;
|
||||
uint32_t diff_samples = rec_samples_ - last_rec_samples_;
|
||||
float rate = diff_samples / (static_cast<float>(time_since_last) / 1000.0);
|
||||
LOG(INFO) << "[REC : " << time_since_last << "msec, "
|
||||
<< rec_sample_rate_ / 1000 << "kHz] callbacks: "
|
||||
<< stats.rec_callbacks - last_stats_.rec_callbacks << ", "
|
||||
<< rec_sample_rate_ / 1000
|
||||
<< "kHz] callbacks: " << rec_callbacks_ - last_rec_callbacks_
|
||||
<< ", "
|
||||
<< "samples: " << diff_samples << ", "
|
||||
<< "rate: " << static_cast<int>(rate + 0.5) << ", "
|
||||
<< "level: " << stats.max_rec_level;
|
||||
<< "level: " << max_rec_level_;
|
||||
|
||||
diff_samples = stats.play_samples - last_stats_.play_samples;
|
||||
diff_samples = play_samples_ - last_play_samples_;
|
||||
rate = diff_samples / (static_cast<float>(time_since_last) / 1000.0);
|
||||
LOG(INFO) << "[PLAY: " << time_since_last << "msec, "
|
||||
<< play_sample_rate_ / 1000 << "kHz] callbacks: "
|
||||
<< stats.play_callbacks - last_stats_.play_callbacks << ", "
|
||||
<< play_sample_rate_ / 1000
|
||||
<< "kHz] callbacks: " << play_callbacks_ - last_play_callbacks_
|
||||
<< ", "
|
||||
<< "samples: " << diff_samples << ", "
|
||||
<< "rate: " << static_cast<int>(rate + 0.5) << ", "
|
||||
<< "level: " << stats.max_play_level;
|
||||
last_stats_ = stats;
|
||||
<< "level: " << max_play_level_;
|
||||
}
|
||||
|
||||
last_rec_callbacks_ = rec_callbacks_;
|
||||
last_play_callbacks_ = play_callbacks_;
|
||||
last_rec_samples_ = rec_samples_;
|
||||
last_play_samples_ = play_samples_;
|
||||
max_rec_level_ = 0;
|
||||
max_play_level_ = 0;
|
||||
|
||||
int64_t time_to_wait_ms = next_callback_time - rtc::TimeMillis();
|
||||
RTC_DCHECK_GT(time_to_wait_ms, 0) << "Invalid timer interval";
|
||||
|
||||
@ -476,37 +495,39 @@ void AudioDeviceBuffer::LogStats(LogState state) {
|
||||
|
||||
void AudioDeviceBuffer::ResetRecStats() {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
last_stats_.ResetRecStats();
|
||||
rtc::CritScope cs(&lock_);
|
||||
stats_.ResetRecStats();
|
||||
rec_callbacks_ = 0;
|
||||
last_rec_callbacks_ = 0;
|
||||
rec_samples_ = 0;
|
||||
last_rec_samples_ = 0;
|
||||
max_rec_level_ = 0;
|
||||
}
|
||||
|
||||
void AudioDeviceBuffer::ResetPlayStats() {
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
last_stats_.ResetPlayStats();
|
||||
rtc::CritScope cs(&lock_);
|
||||
stats_.ResetPlayStats();
|
||||
play_callbacks_ = 0;
|
||||
last_play_callbacks_ = 0;
|
||||
play_samples_ = 0;
|
||||
last_play_samples_ = 0;
|
||||
max_play_level_ = 0;
|
||||
}
|
||||
|
||||
void AudioDeviceBuffer::UpdateRecStats(int16_t max_abs,
|
||||
size_t samples_per_channel) {
|
||||
RTC_DCHECK_RUN_ON(&recording_thread_checker_);
|
||||
rtc::CritScope cs(&lock_);
|
||||
++stats_.rec_callbacks;
|
||||
stats_.rec_samples += samples_per_channel;
|
||||
if (max_abs > stats_.max_rec_level) {
|
||||
stats_.max_rec_level = max_abs;
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
++rec_callbacks_;
|
||||
rec_samples_ += samples_per_channel;
|
||||
if (max_abs > max_rec_level_) {
|
||||
max_rec_level_ = max_abs;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioDeviceBuffer::UpdatePlayStats(int16_t max_abs,
|
||||
size_t samples_per_channel) {
|
||||
RTC_DCHECK_RUN_ON(&playout_thread_checker_);
|
||||
rtc::CritScope cs(&lock_);
|
||||
++stats_.play_callbacks;
|
||||
stats_.play_samples += samples_per_channel;
|
||||
if (max_abs > stats_.max_play_level) {
|
||||
stats_.max_play_level = max_abs;
|
||||
RTC_DCHECK_RUN_ON(&task_queue_);
|
||||
++play_callbacks_;
|
||||
play_samples_ += samples_per_channel;
|
||||
if (max_abs > max_play_level_) {
|
||||
max_play_level_ = max_abs;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -12,7 +12,6 @@
|
||||
#define WEBRTC_MODULES_AUDIO_DEVICE_AUDIO_DEVICE_BUFFER_H_
|
||||
|
||||
#include "webrtc/base/buffer.h"
|
||||
#include "webrtc/base/criticalsection.h"
|
||||
#include "webrtc/base/task_queue.h"
|
||||
#include "webrtc/base/thread_annotations.h"
|
||||
#include "webrtc/base/thread_checker.h"
|
||||
@ -37,43 +36,6 @@ class AudioDeviceBuffer {
|
||||
LOG_ACTIVE,
|
||||
};
|
||||
|
||||
struct Stats {
|
||||
void ResetRecStats() {
|
||||
rec_callbacks = 0;
|
||||
rec_samples = 0;
|
||||
max_rec_level = 0;
|
||||
}
|
||||
|
||||
void ResetPlayStats() {
|
||||
play_callbacks = 0;
|
||||
play_samples = 0;
|
||||
max_play_level = 0;
|
||||
}
|
||||
|
||||
// Total number of recording callbacks where the source provides 10ms audio
|
||||
// data each time.
|
||||
uint64_t rec_callbacks = 0;
|
||||
|
||||
// Total number of playback callbacks where the sink asks for 10ms audio
|
||||
// data each time.
|
||||
uint64_t play_callbacks = 0;
|
||||
|
||||
// Total number of recorded audio samples.
|
||||
uint64_t rec_samples = 0;
|
||||
|
||||
// Total number of played audio samples.
|
||||
uint64_t play_samples = 0;
|
||||
|
||||
// Contains max level (max(abs(x))) of recorded audio packets over the last
|
||||
// 10 seconds where a new measurement is done twice per second. The level
|
||||
// is reset to zero at each call to LogStats().
|
||||
int16_t max_rec_level = 0;
|
||||
|
||||
// Contains max level of recorded audio packets over the last 10 seconds
|
||||
// where a new measurement is done twice per second.
|
||||
int16_t max_play_level = 0;
|
||||
};
|
||||
|
||||
AudioDeviceBuffer();
|
||||
virtual ~AudioDeviceBuffer();
|
||||
|
||||
@ -130,8 +92,9 @@ class AudioDeviceBuffer {
|
||||
// state = LOG_ACTIVE => logs are printed and the timer is kept alive.
|
||||
void LogStats(LogState state);
|
||||
|
||||
// Updates counters in each play/record callback. These counters are later
|
||||
// (periodically) read by LogStats() using a lock.
|
||||
// Updates counters in each play/record callback but does it on the task
|
||||
// queue to ensure that they can be read by LogStats() without any locks since
|
||||
// each task is serialized by the task queue.
|
||||
void UpdateRecStats(int16_t max_abs, size_t samples_per_channel);
|
||||
void UpdatePlayStats(int16_t max_abs, size_t samples_per_channel);
|
||||
|
||||
@ -157,8 +120,6 @@ class AudioDeviceBuffer {
|
||||
// Native (platform specific) audio thread driving the recording side.
|
||||
rtc::ThreadChecker recording_thread_checker_;
|
||||
|
||||
rtc::CriticalSection lock_;
|
||||
|
||||
// Task queue used to invoke LogStats() periodically. Tasks are executed on a
|
||||
// worker thread but it does not necessarily have to be the same thread for
|
||||
// each task.
|
||||
@ -223,6 +184,41 @@ class AudioDeviceBuffer {
|
||||
// Counts number of times LogStats() has been called.
|
||||
size_t num_stat_reports_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Total number of recording callbacks where the source provides 10ms audio
|
||||
// data each time.
|
||||
uint64_t rec_callbacks_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Total number of recording callbacks stored at the last timer task.
|
||||
uint64_t last_rec_callbacks_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Total number of playback callbacks where the sink asks for 10ms audio
|
||||
// data each time.
|
||||
uint64_t play_callbacks_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Total number of playout callbacks stored at the last timer task.
|
||||
uint64_t last_play_callbacks_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Total number of recorded audio samples.
|
||||
uint64_t rec_samples_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Total number of recorded samples stored at the previous timer task.
|
||||
uint64_t last_rec_samples_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Total number of played audio samples.
|
||||
uint64_t play_samples_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Total number of played samples stored at the previous timer task.
|
||||
uint64_t last_play_samples_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Contains max level (max(abs(x))) of recorded audio packets over the last
|
||||
// 10 seconds where a new measurement is done twice per second. The level
|
||||
// is reset to zero at each call to LogStats().
|
||||
int16_t max_rec_level_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Contains max level of recorded audio packets over the last 10 seconds
|
||||
// where a new measurement is done twice per second.
|
||||
int16_t max_play_level_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Time stamp of last timer task (drives logging).
|
||||
int64_t last_timer_task_time_ ACCESS_ON(task_queue_);
|
||||
|
||||
@ -235,13 +231,6 @@ class AudioDeviceBuffer {
|
||||
int64_t play_start_time_ ACCESS_ON(main_thread_checker_);
|
||||
int64_t rec_start_time_ ACCESS_ON(main_thread_checker_);
|
||||
|
||||
// Contains counters for playout and recording statistics.
|
||||
Stats stats_ GUARDED_BY(lock_);
|
||||
|
||||
// Stores current stats at each timer task. Used to calculate differences
|
||||
// between two successive timer events.
|
||||
Stats last_stats_ ACCESS_ON(task_queue_);
|
||||
|
||||
// Set to true at construction and modified to false as soon as one audio-
|
||||
// level estimate larger than zero is detected.
|
||||
bool only_silence_recorded_;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user