perf(server): dont record Idle time when not needed

This commit is contained in:
Sean McArthur
2017-06-23 18:52:32 -07:00
parent 7d122bd15f
commit 4dfe0db0f4
3 changed files with 31 additions and 18 deletions

View File

@@ -80,7 +80,7 @@ impl<T: Clone> Pool<T> {
entry: Entry { entry: Entry {
value: value, value: value,
is_reused: false, is_reused: false,
status: Rc::new(Cell::new(KA::Busy)), status: Rc::new(Cell::new(TimedKA::Busy)),
}, },
key: key, key: key,
pool: self.clone(), pool: self.clone(),
@@ -94,7 +94,7 @@ impl<T: Clone> Pool<T> {
fn reuse(&self, key: Rc<String>, mut entry: Entry<T>) -> Pooled<T> { fn reuse(&self, key: Rc<String>, mut entry: Entry<T>) -> Pooled<T> {
trace!("Pool::reuse {:?}", key); trace!("Pool::reuse {:?}", key);
entry.is_reused = true; entry.is_reused = true;
entry.status.set(KA::Busy); entry.status.set(TimedKA::Busy);
Pooled { Pooled {
entry: entry, entry: entry,
key: key, key: key,
@@ -141,17 +141,17 @@ impl<T> DerefMut for Pooled<T> {
impl<T: Clone> KeepAlive for Pooled<T> { impl<T: Clone> KeepAlive for Pooled<T> {
fn busy(&mut self) { fn busy(&mut self) {
self.entry.status.set(KA::Busy); self.entry.status.set(TimedKA::Busy);
} }
fn disable(&mut self) { fn disable(&mut self) {
self.entry.status.set(KA::Disabled); self.entry.status.set(TimedKA::Disabled);
} }
fn idle(&mut self) { fn idle(&mut self) {
let previous = self.status(); let previous = self.status();
self.entry.status.set(KA::Idle(Instant::now())); self.entry.status.set(TimedKA::Idle(Instant::now()));
if let KA::Idle(..) = previous { if let KA::Idle = previous {
trace!("Pooled::idle already idle"); trace!("Pooled::idle already idle");
return; return;
} }
@@ -162,7 +162,11 @@ impl<T: Clone> KeepAlive for Pooled<T> {
} }
fn status(&self) -> KA { fn status(&self) -> KA {
self.entry.status.get() match self.entry.status.get() {
TimedKA::Idle(_) => KA::Idle,
TimedKA::Busy => KA::Busy,
TimedKA::Disabled => KA::Disabled,
}
} }
} }
@@ -187,7 +191,14 @@ impl<T: Clone> BitAndAssign<bool> for Pooled<T> {
struct Entry<T> { struct Entry<T> {
value: T, value: T,
is_reused: bool, is_reused: bool,
status: Rc<Cell<KA>>, status: Rc<Cell<TimedKA>>,
}
#[derive(Clone, Copy, Debug)]
enum TimedKA {
Idle(Instant),
Busy,
Disabled,
} }
pub struct Checkout<T> { pub struct Checkout<T> {
@@ -224,7 +235,7 @@ impl<T: Clone> Future for Checkout<T> {
trace!("Checkout::poll key found {:?}", key); trace!("Checkout::poll key found {:?}", key);
while let Some(entry) = list.pop() { while let Some(entry) = list.pop() {
match entry.status.get() { match entry.status.get() {
KA::Idle(idle_at) if !expiration.expires(idle_at) => { TimedKA::Idle(idle_at) if !expiration.expires(idle_at) => {
trace!("Checkout::poll found idle client for {:?}", key); trace!("Checkout::poll found idle client for {:?}", key);
should_remove = list.is_empty(); should_remove = list.is_empty();
return Some(entry); return Some(entry);

View File

@@ -1,7 +1,6 @@
use std::fmt; use std::fmt;
use std::io::{self, Write}; use std::io::{self, Write};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::time::Instant;
use futures::{Poll, Async, AsyncSink, Stream, Sink, StartSend}; use futures::{Poll, Async, AsyncSink, Stream, Sink, StartSend};
use futures::task::Task; use futures::task::Task;
@@ -228,10 +227,7 @@ where I: AsyncRead + AsyncWrite,
let wants_keep_alive = head.should_keep_alive(); let wants_keep_alive = head.should_keep_alive();
self.state.keep_alive &= wants_keep_alive; self.state.keep_alive &= wants_keep_alive;
let mut buf = Vec::new(); let encoder = T::encode(head, self.io.write_buf_mut());
let encoder = T::encode(head, &mut buf);
//TODO: handle when there isn't enough room to buffer the head
assert!(self.io.buffer(buf) > 0);
self.state.writing = if body { self.state.writing = if body {
Writing::Body(encoder, None) Writing::Body(encoder, None)
} else { } else {
@@ -534,7 +530,7 @@ pub trait KeepAlive: fmt::Debug + ::std::ops::BitAndAssign<bool> {
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum KA { pub enum KA {
Idle(Instant), Idle,
Busy, Busy,
Disabled, Disabled,
} }
@@ -547,7 +543,7 @@ impl Default for KA {
impl KeepAlive for KA { impl KeepAlive for KA {
fn idle(&mut self) { fn idle(&mut self) {
*self = KA::Idle(Instant::now()); *self = KA::Idle;
} }
fn busy(&mut self) { fn busy(&mut self) {
@@ -595,7 +591,7 @@ impl<B, K: KeepAlive> State<B, K> {
} }
fn is_idle(&self) -> bool { fn is_idle(&self) -> bool {
if let KA::Idle(..) = self.keep_alive.status() { if let KA::Idle = self.keep_alive.status() {
true true
} else { } else {
false false

View File

@@ -42,6 +42,12 @@ impl<T: AsyncRead + AsyncWrite> Buffered<T> {
self.read_buf.as_ref() self.read_buf.as_ref()
} }
pub fn write_buf_mut(&mut self) -> &mut Vec<u8> {
self.write_buf.maybe_reset();
self.write_buf.maybe_reserve(0);
&mut self.write_buf.0.bytes
}
pub fn consume_leading_lines(&mut self) { pub fn consume_leading_lines(&mut self) {
if !self.read_buf.is_empty() { if !self.read_buf.is_empty() {
let mut i = 0; let mut i = 0;
@@ -133,7 +139,7 @@ impl<T: Write> Write for Buffered<T> {
} else { } else {
loop { loop {
let n = try!(self.write_buf.write_into(&mut self.io)); let n = try!(self.write_buf.write_into(&mut self.io));
debug!("flushed {} bytes", n); trace!("flushed {} bytes", n);
if self.write_buf.remaining() == 0 { if self.write_buf.remaining() == 0 {
break; break;
} }