This is an automated email from the ASF dual-hosted git repository.

xuanwo pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/opendal.git


The following commit(s) were added to refs/heads/main by this push:
     new 8e84d81486 refactor(core): Polish FuturesBytesStream by avoiding extra 
copy (#4474)
8e84d81486 is described below

commit 8e84d8148606ca0138bdc7e9f0c18e0e7436a944
Author: Xuanwo <[email protected]>
AuthorDate: Sat Apr 13 11:13:02 2024 +0800

    refactor(core): Polish FuturesBytesStream by avoiding extra copy (#4474)
    
    * refactor(core): Polish FuturesBytesStream by avoiding extra copy
    
    Signed-off-by: Xuanwo <[email protected]>
    
    * remove not needed read at static
    
    Signed-off-by: Xuanwo <[email protected]>
    
    * cleanup
    
    Signed-off-by: Xuanwo <[email protected]>
    
    ---------
    
    Signed-off-by: Xuanwo <[email protected]>
---
 core/src/raw/oio/read/api.rs | 22 ----------------------
 core/src/types/reader.rs     | 39 +++++++++++++++++++--------------------
 2 files changed, 19 insertions(+), 42 deletions(-)

diff --git a/core/src/raw/oio/read/api.rs b/core/src/raw/oio/read/api.rs
index 46332eb20e..c874dd089e 100644
--- a/core/src/raw/oio/read/api.rs
+++ b/core/src/raw/oio/read/api.rs
@@ -84,14 +84,11 @@ pub trait Read: Unpin + Send + Sync {
     ///
     /// Storage services should try to read as much as possible, only return 
bytes less than the
     /// limit while reaching the end of the file.
-    #[cfg(not(target_arch = "wasm32"))]
     fn read_at(
         &self,
         offset: u64,
         limit: usize,
     ) -> impl Future<Output = Result<Buffer>> + MaybeSend;
-    #[cfg(target_arch = "wasm32")]
-    fn read_at(&self, offset: u64, limit: usize) -> impl Future<Output = 
Result<Buffer>>;
 }
 
 impl Read for () {
@@ -124,31 +121,12 @@ pub trait ReadDyn: Unpin + Send + Sync {
     ///
     /// This function returns a boxed future to make it object safe.
     fn read_at_dyn(&self, offset: u64, limit: usize) -> 
BoxedFuture<Result<Buffer>>;
-
-    /// The static version of [`Read::read_at`].
-    ///
-    /// This function returns a `'static` future by moving `self` into the
-    /// future. Caller can call `Box::pin` to build a static boxed future.
-    fn read_at_static(
-        self,
-        offset: u64,
-        limit: usize,
-    ) -> impl Future<Output = Result<Buffer>> + MaybeSend + 'static
-    where
-        Self: Sized + 'static;
 }
 
 impl<T: Read + ?Sized> ReadDyn for T {
     fn read_at_dyn(&self, offset: u64, limit: usize) -> 
BoxedFuture<Result<Buffer>> {
         Box::pin(self.read_at(offset, limit))
     }
-
-    async fn read_at_static(self, offset: u64, limit: usize) -> Result<Buffer>
-    where
-        Self: Sized + 'static,
-    {
-        self.read_at(offset, limit).await
-    }
 }
 
 /// # NOTE
diff --git a/core/src/types/reader.rs b/core/src/types/reader.rs
index 4031ac79a5..cc82a645e0 100644
--- a/core/src/types/reader.rs
+++ b/core/src/types/reader.rs
@@ -127,7 +127,6 @@ pub mod into_stream {
         sync::{atomic::AtomicBool, Arc},
     };
 
-    use crate::raw::oio::ReadDyn;
     use crate::raw::*;
     use crate::*;
 
@@ -183,7 +182,7 @@ pub mod into_stream {
             // Update self.offset before building future.
             self.offset += limit as u64;
             let fut = async move {
-                let buf = r.read_at_static(offset, limit).await?;
+                let buf = r.read_at_dyn(offset, limit).await?;
                 if buf.len() < limit || limit == 0 {
                     // Update finished marked if buf is less than limit.
                     finished.store(true, Ordering::Relaxed);
@@ -363,7 +362,6 @@ pub mod into_futures_stream {
     use std::task::Context;
     use std::task::Poll;
 
-    use bytes::Buf;
     use bytes::Bytes;
     use futures::Stream;
 
@@ -376,6 +374,7 @@ pub mod into_futures_stream {
     ///
     /// FuturesStream also implements [`Unpin`], [`Send`] and [`Sync`].
     pub struct FuturesBytesStream {
+        r: oio::Reader,
         state: State,
         offset: u64,
         size: u64,
@@ -385,8 +384,8 @@ pub mod into_futures_stream {
     }
 
     enum State {
-        Idle(Option<oio::Reader>),
-        Next(BoxedStaticFuture<(oio::Reader, Result<Buffer>)>),
+        Idle(Buffer),
+        Next(BoxedStaticFuture<Result<Buffer>>),
     }
 
     /// # Safety
@@ -399,7 +398,8 @@ pub mod into_futures_stream {
         #[inline]
         pub(crate) fn new(r: oio::Reader, range: Range<u64>) -> Self {
             FuturesBytesStream {
-                state: State::Idle(Some(r)),
+                r,
+                state: State::Idle(Buffer::new()),
                 offset: range.start,
                 size: range.end - range.start,
                 // TODO: should use services preferred io size.
@@ -424,31 +424,30 @@ pub mod into_futures_stream {
 
             loop {
                 match &mut this.state {
-                    State::Idle(r) => {
+                    State::Idle(buf) => {
+                        // Consume current buffer
+                        if let Some(bs) = buf.next() {
+                            return Poll::Ready(Some(Ok(bs)));
+                        }
+
                         // Make sure cur didn't exceed size.
                         if this.cur >= this.size {
                             return Poll::Ready(None);
                         }
 
-                        let r = r.take().expect("reader must be present");
+                        let r = this.r.clone();
                         let next_offset = this.offset + this.cur;
                         let next_size = (this.size - this.cur).min(this.cap as 
u64) as usize;
-                        let fut = async move {
-                            let res = r.read_at_dyn(next_offset, 
next_size).await;
-                            (r, res)
-                        };
+                        let fut = async move { r.read_at_dyn(next_offset, 
next_size).await };
                         this.state = State::Next(Box::pin(fut));
                     }
                     State::Next(fut) => {
-                        let (r, res) = ready!(fut.as_mut().poll(cx));
-                        this.state = State::Idle(Some(r));
-                        return match res {
-                            Ok(buf) if !buf.has_remaining() => 
Poll::Ready(None),
-                            Ok(mut buf) => {
-                                this.cur += buf.remaining() as u64;
-                                
Poll::Ready(Some(Ok(buf.copy_to_bytes(buf.remaining()))))
+                        let res = ready!(fut.as_mut().poll(cx));
+                        match res {
+                            Ok(buf) => {
+                                this.state = State::Idle(buf);
                             }
-                            Err(err) => 
Poll::Ready(Some(Err(format_std_io_error(err)))),
+                            Err(err) => return 
Poll::Ready(Some(Err(format_std_io_error(err)))),
                         };
                     }
                 }

Reply via email to