Skip to content

Commit

Permalink
fix: 部分场景fps测量过大
Browse files Browse the repository at this point in the history
  • Loading branch information
shadow3aaa committed Oct 3, 2024
1 parent eadf83f commit 6a19ba8
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 23 deletions.
26 changes: 21 additions & 5 deletions examples/simple-analyzer/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,13 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::sync::{
atomic::{AtomicBool, Ordering},
Arc,
use std::{
collections::VecDeque,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
time::Duration,
};

use anyhow::Result;
Expand Down Expand Up @@ -50,9 +54,21 @@ fn main() -> Result<()> {
})?;
}

let mut buffer = VecDeque::with_capacity(120);

while running.load(Ordering::Acquire) {
if let Some((_, frametime)) = analyzer.recv() {
println!("frametime: {frametime:?}");
if let Some((pid, frametime)) = analyzer.recv() {
println!("frametime: {frametime:?}, pid: {pid}");
if buffer.len() >= 120 {
buffer.pop_back();
}
buffer.push_front(frametime);
if buffer.len() == 120 {
let fps = 1.0
/ (buffer.iter().copied().sum::<Duration>() / buffer.len() as u32)
.as_secs_f64();
println!("{fps}");
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions frame-analyzer-ebpf-common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@
#[repr(C)]
pub struct FrameSignal {
pub ktime_ns: u64,
pub buffer: usize,
}

impl FrameSignal {
pub const fn new(ktime_ns: u64) -> Self {
Self { ktime_ns }
pub const fn new(ktime_ns: u64, buffer: usize) -> Self {
Self { ktime_ns, buffer }
}
}
4 changes: 2 additions & 2 deletions frame-analyzer-ebpf/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ pub fn frame_analyzer_ebpf(ctx: ProbeContext) -> u32 {
}
}

fn try_frame_analyzer_ebpf(_ctx: ProbeContext) -> Result<u32, u32> {
fn try_frame_analyzer_ebpf(ctx: ProbeContext) -> Result<u32, u32> {
if let Some(mut entry) = RING_BUF.reserve::<FrameSignal>(0) {
let ktime_ns = unsafe { bpf_ktime_get_ns() };
entry.write(FrameSignal::new(ktime_ns));
entry.write(FrameSignal::new(ktime_ns, ctx.arg::<usize>(0).unwrap()));
entry.submit(0);
}

Expand Down
45 changes: 33 additions & 12 deletions frame-analyzer/src/analyze_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,37 +16,58 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
use std::{ptr, time::Duration};
use std::{
collections::{HashMap, VecDeque},
ptr,
time::Duration,
};

use frame_analyzer_ebpf_common::FrameSignal;

use crate::{error::Result, uprobe::UprobeHandler};
use crate::uprobe::UprobeHandler;

pub struct AnalyzeTarget {
pub uprobe: UprobeHandler,
ktime_us_last: Option<u64>,
buffers: HashMap<usize, (u64, VecDeque<Duration>)>,
}

impl AnalyzeTarget {
pub fn new(uprobe: UprobeHandler) -> Self {
Self {
uprobe,
ktime_us_last: None,
buffers: HashMap::new(),
}
}

pub fn update(&mut self) -> Result<Duration> {
let mut frametime = 0;
if let Some(item) = self.uprobe.ring()?.next() {
let frame = unsafe { trans(&item) };
pub fn update(&mut self) -> Option<Duration> {
let mut ring = self.uprobe.ring().unwrap();
let item = ring.next()?;
let event = unsafe { trans(&item) };
if let Some((timestamp, buffer)) = self.buffers.get_mut(&event.buffer) {
let frametime = event.ktime_ns.saturating_sub(*timestamp);
*timestamp = event.ktime_ns;

if let Some(ktime_us_last) = self.ktime_us_last {
frametime = frame.ktime_ns.saturating_sub(ktime_us_last);
if buffer.len() >= 144 {
buffer.pop_back();
}
self.ktime_us_last = Some(frame.ktime_ns);

buffer.push_front(Duration::from_nanos(frametime));
} else {
self.buffers
.insert(event.buffer, (event.ktime_ns, VecDeque::with_capacity(144)));
}

Ok(Duration::from_nanos(frametime))
if self.buffers.get(&event.buffer)
== self
.buffers
.values()
.filter(|(_, buffer)| buffer.len() == 144)
.min_by_key(|(_, buffer)| buffer.iter().copied().sum::<Duration>())
{
self.buffers.get(&event.buffer)?.1.front().copied()
} else {
None
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions frame-analyzer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ impl Analyzer {
}

let pid = self.buffer.pop_front()?;
let frametime = self.map.get_mut(&pid)?.update().ok()?;
let frametime = self.map.get_mut(&pid)?.update()?;

Some((pid, frametime))
}
Expand Down Expand Up @@ -315,7 +315,7 @@ impl Analyzer {
}

let pid = self.buffer.pop_front()?;
let frametime = self.map.get_mut(&pid)?.update().ok()?;
let frametime = self.map.get_mut(&pid)?.update()?;

Some((pid, frametime))
}
Expand Down

0 comments on commit 6a19ba8

Please sign in to comment.