浏览代码

aya: perf_buffer: call BytesMut::reserve() internally

This changes PerfBuffer::read_events() to call BytesMut::reserve()
internally, and deprecates PerfBufferError::MoreSpaceNeeded.

This makes for a more ergonomic API, and allows for a more idiomatic
usage of BytesMut. For example consider:

    let mut buffers = vec![BytesMut::with_capacity(N), ...];
    loop {
        let events = oob_cpu_buf.read_events(&mut buffers).unwrap();
        for buf in &mut buffers[..events.read] {
            let sub: Bytes = buf.split_off(n).into();
            process_sub_buf(sub);
        }
        ...
    }

This is a common way to process perf bufs, where a sub buffer is split
off from the original buffer and then processed. In the next iteration
of the loop when it's time to read again, two things can happen:

- if processing of the sub buffer is complete and `sub` has been
dropped, read_events() will call buf.reserve(sample_size) and hit a fast
path in BytesMut that will just restore the original capacity of the
buffer (assuming sample_size <= N).

- if processing of the sub buffer hasn't ended (eg the buffer has been
stored or is being processed in another thread),
buf.reserve(sample_size) will actually allocate the new memory required
to read the sample.

In other words, calling buf.reserve(sample_size) inside read_events()
simplifies doing zero-copy processing of buffers in many cases.
Alessandro Decina 3 年之前
父节点
当前提交
ad1636d2e7
共有 2 个文件被更改,包括 5 次插入13 次删除
  1. 5 10
      aya/src/maps/perf/perf_buffer.rs
  2. 0 3
      aya/src/maps/perf/perf_event_array.rs

+ 5 - 10
aya/src/maps/perf/perf_buffer.rs

@@ -59,6 +59,10 @@ pub enum PerfBufferError {
 
     /// `read_events()` was called with a buffer that is not large enough to
     /// contain the next event in the perf buffer.
+    #[deprecated(
+        since = "0.10.8",
+        note = "read_events() now calls BytesMut::reserve() internally, so this error is never returned"
+    )]
     #[error("the buffer needs to be of at least {size} bytes")]
     MoreSpaceNeeded {
         /// expected size
@@ -192,10 +196,7 @@ impl PerfBuffer {
             match event_type {
                 x if x == PERF_RECORD_SAMPLE as u32 => {
                     buf.clear();
-                    if sample_size > buf.capacity() {
-                        return Err(PerfBufferError::MoreSpaceNeeded { size: sample_size });
-                    }
-
+                    buf.reserve(sample_size);
                     unsafe { buf.set_len(sample_size) };
 
                     fill_buf(sample_start, base, self.size, buf);
@@ -239,12 +240,6 @@ impl PerfBuffer {
                     events.lost += lost;
                 }
                 Ok(None) => { /* skip unknown event type */ }
-                Err(PerfBufferError::MoreSpaceNeeded { .. }) if events.read > 0 => {
-                    // we have processed some events so we're going to return those. In the
-                    // next read_events() we'll return an error unless the caller increases the
-                    // buffer size
-                    break;
-                }
                 Err(e) => {
                     // we got an error and we didn't process any events, propagate the error
                     // and give the caller a chance to increase buffers

+ 0 - 3
aya/src/maps/perf/perf_event_array.rs

@@ -51,9 +51,6 @@ impl<T: DerefMut<Target = Map>> PerfEventArrayBuffer<T> {
     /// # Errors
     ///
     /// [`PerfBufferError::NoBuffers`] is returned when `out_bufs` is empty.
-    ///
-    /// [`PerfBufferError::MoreSpaceNeeded { size }`](PerfBufferError) is returned when the size of the events is
-    /// bigger than the size of the out_bufs provided.
     pub fn read_events(&mut self, out_bufs: &mut [BytesMut]) -> Result<Events, PerfBufferError> {
         self.buf.read_events(out_bufs)
     }