mirror of
https://github.com/tokio-rs/tokio.git
synced 2026-09-07 00:00:08 +02:00
Merge pull request #166 from Byron/master
Allocation in get_mut() always uses 8 * 1024 bytes
This commit is contained in:
+24
-9
@@ -1,6 +1,7 @@
|
|||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::cmp;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -8,6 +9,8 @@ use futures::{Async, Poll, Stream, Sink, StartSend, AsyncSink};
|
|||||||
|
|
||||||
use io::Io;
|
use io::Io;
|
||||||
|
|
||||||
|
const INITIAL_CAPACITY: usize = 8 * 1024;
|
||||||
|
|
||||||
/// A reference counted buffer of bytes.
|
/// A reference counted buffer of bytes.
|
||||||
///
|
///
|
||||||
/// An `EasyBuf` is a representation of a byte buffer where sub-slices of it can
|
/// An `EasyBuf` is a representation of a byte buffer where sub-slices of it can
|
||||||
@@ -31,7 +34,7 @@ pub struct EasyBufMut<'a> {
|
|||||||
impl EasyBuf {
|
impl EasyBuf {
|
||||||
/// Creates a new EasyBuf with no data and the default capacity.
|
/// Creates a new EasyBuf with no data and the default capacity.
|
||||||
pub fn new() -> EasyBuf {
|
pub fn new() -> EasyBuf {
|
||||||
EasyBuf::with_capacity(8 * 1024)
|
EasyBuf::with_capacity(INITIAL_CAPACITY)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new EasyBuf with `cap` capacity.
|
/// Creates a new EasyBuf with `cap` capacity.
|
||||||
@@ -126,8 +129,8 @@ impl EasyBuf {
|
|||||||
/// If this `EasyBuf` is the only instance pointing at the underlying buffer
|
/// If this `EasyBuf` is the only instance pointing at the underlying buffer
|
||||||
/// of bytes, a direct mutable reference will be returned. Otherwise the
|
/// of bytes, a direct mutable reference will be returned. Otherwise the
|
||||||
/// contents of this `EasyBuf` will be reallocated in a fresh `Vec<u8>`
|
/// contents of this `EasyBuf` will be reallocated in a fresh `Vec<u8>`
|
||||||
/// allocation with the same capacity as this allocation, and that
|
/// allocation with the same capacity as an `EasyBuf` created with `EasyBuf::new()`,
|
||||||
/// allocation will be returned.
|
/// and that allocation will be returned.
|
||||||
///
|
///
|
||||||
/// This operation **is not O(1)** as it may clone the entire contents of
|
/// This operation **is not O(1)** as it may clone the entire contents of
|
||||||
/// this buffer.
|
/// this buffer.
|
||||||
@@ -150,7 +153,7 @@ impl EasyBuf {
|
|||||||
|
|
||||||
// If we couldn't get access above then we give ourself a new buffer
|
// If we couldn't get access above then we give ourself a new buffer
|
||||||
// here.
|
// here.
|
||||||
let mut v = Vec::with_capacity(self.buf.capacity());
|
let mut v = Vec::with_capacity(cmp::max(INITIAL_CAPACITY, self.as_ref().len()));
|
||||||
v.extend_from_slice(self.as_ref());
|
v.extend_from_slice(self.as_ref());
|
||||||
self.start = 0;
|
self.start = 0;
|
||||||
self.buf = Arc::new(v);
|
self.buf = Arc::new(v);
|
||||||
@@ -345,9 +348,10 @@ impl<T: Io, C: Codec> Sink for Framed<T, C> {
|
|||||||
fn start_send(&mut self, item: C::Out) -> StartSend<C::Out, io::Error> {
|
fn start_send(&mut self, item: C::Out) -> StartSend<C::Out, io::Error> {
|
||||||
// If the buffer is already over 8KiB, then attempt to flush it. If after flushing it's
|
// If the buffer is already over 8KiB, then attempt to flush it. If after flushing it's
|
||||||
// *still* over 8KiB, then apply backpressure (reject the send).
|
// *still* over 8KiB, then apply backpressure (reject the send).
|
||||||
if self.wr.len() > 8 * 1024 {
|
const BACKPRESSURE_BOUNDARY: usize = INITIAL_CAPACITY;
|
||||||
|
if self.wr.len() > BACKPRESSURE_BOUNDARY {
|
||||||
try!(self.poll_complete());
|
try!(self.poll_complete());
|
||||||
if self.wr.len() > 8 * 1024 {
|
if self.wr.len() > BACKPRESSURE_BOUNDARY {
|
||||||
return Ok(AsyncSink::NotReady(item));
|
return Ok(AsyncSink::NotReady(item));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,7 +388,7 @@ pub fn framed<T, C>(io: T, codec: C) -> Framed<T, C> {
|
|||||||
eof: false,
|
eof: false,
|
||||||
is_readable: false,
|
is_readable: false,
|
||||||
rd: EasyBuf::new(),
|
rd: EasyBuf::new(),
|
||||||
wr: Vec::with_capacity(8 * 1024),
|
wr: Vec::with_capacity(INITIAL_CAPACITY),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,7 +425,7 @@ impl<T, C> Framed<T, C> {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::EasyBuf;
|
use super::{INITIAL_CAPACITY, EasyBuf};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -461,7 +465,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn easybuf_get_mut_sliced_allocating() {
|
fn easybuf_get_mut_sliced_allocating_at_least_initial_capacity() {
|
||||||
let vec: Vec<u8> = (0u8..10u8).collect();
|
let vec: Vec<u8> = (0u8..10u8).collect();
|
||||||
let mut buf: EasyBuf = vec.into();
|
let mut buf: EasyBuf = vec.into();
|
||||||
buf.split_off(9);
|
buf.split_off(9);
|
||||||
@@ -469,9 +473,20 @@ mod tests {
|
|||||||
// Clone to make shared
|
// Clone to make shared
|
||||||
let clone = buf.clone();
|
let clone = buf.clone();
|
||||||
assert_eq!(*buf.get_mut(), [3, 4, 5, 6, 7, 8]);
|
assert_eq!(*buf.get_mut(), [3, 4, 5, 6, 7, 8]);
|
||||||
|
assert_eq!(buf.get_mut().buf.capacity(), INITIAL_CAPACITY);
|
||||||
mem::drop(clone); // prevent unused warning
|
mem::drop(clone); // prevent unused warning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn easybuf_get_mut_sliced_allocating_required_capacity() {
|
||||||
|
let vec: Vec<u8> = (0..INITIAL_CAPACITY * 2).map(|_|0u8).collect();
|
||||||
|
let mut buf: EasyBuf = vec.into();
|
||||||
|
buf.drain_to(INITIAL_CAPACITY / 2);
|
||||||
|
let clone = buf.clone();
|
||||||
|
assert_eq!(buf.get_mut().buf.capacity(), INITIAL_CAPACITY + INITIAL_CAPACITY / 2);
|
||||||
|
mem::drop(clone)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn easybuf_into_vec_simple() {
|
fn easybuf_into_vec_simple() {
|
||||||
let vec: Vec<u8> = (0u8..10u8).collect();
|
let vec: Vec<u8> = (0u8..10u8).collect();
|
||||||
|
|||||||
Reference in New Issue
Block a user