mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-23 16:21:06 +01:00
fix continous growth of app data in pooled requests (#1609)
fixes #1606 fixes #1607
This commit is contained in:
parent
2fd96c03e5
commit
971ba3eee1
@ -1,6 +1,10 @@
|
||||
# Changes
|
||||
|
||||
## Unreleased - 2020-xx-xx
|
||||
### Fixed
|
||||
* Memory leak of app data in pooled requests. [#1609]
|
||||
|
||||
[#1609]: https://github.com/actix/actix-web/pull/1609
|
||||
|
||||
|
||||
## 3.0.0-beta.1 - 2020-07-13
|
||||
|
@ -10,6 +10,7 @@ use actix_router::{Path, ResourceDef, ResourceInfo, Router, Url};
|
||||
use actix_service::boxed::{self, BoxService, BoxServiceFactory};
|
||||
use actix_service::{fn_service, Service, ServiceFactory};
|
||||
use futures_util::future::{join_all, ok, FutureExt, LocalBoxFuture};
|
||||
use tinyvec::tiny_vec;
|
||||
|
||||
use crate::config::{AppConfig, AppService};
|
||||
use crate::data::{DataFactory, FnDataFactory};
|
||||
@ -245,7 +246,7 @@ where
|
||||
inner.path.reset();
|
||||
inner.head = head;
|
||||
inner.payload = payload;
|
||||
inner.app_data.push(self.data.clone());
|
||||
inner.app_data = tiny_vec![self.data.clone()];
|
||||
req
|
||||
} else {
|
||||
HttpRequest::new(
|
||||
|
@ -276,6 +276,7 @@ impl HttpMessage for HttpRequest {
|
||||
|
||||
impl Drop for HttpRequest {
|
||||
fn drop(&mut self) {
|
||||
// if possible, contribute to current worker's HttpRequest allocation pool
|
||||
if Rc::strong_count(&self.0) == 1 {
|
||||
let v = &mut self.0.pool.0.borrow_mut();
|
||||
if v.len() < 128 {
|
||||
@ -340,25 +341,32 @@ impl fmt::Debug for HttpRequest {
|
||||
}
|
||||
}
|
||||
|
||||
/// Request's objects pool
|
||||
/// Slab-allocated `HttpRequest` Pool
|
||||
///
|
||||
/// Since request processing may yield for asynchronous events to complete, a worker may have many
|
||||
/// requests in-flight at any time. Pooling requests like this amortizes the performance and memory
|
||||
/// costs of allocating and de-allocating HttpRequest objects as frequently as they otherwise would.
|
||||
///
|
||||
/// Request objects are added when they are dropped (see `<HttpRequest as Drop>::drop`) and re-used
|
||||
/// in `<AppInitService as Service>::call` when there are available objects in the list.
|
||||
///
|
||||
/// The pool's initial capacity is 128 items.
|
||||
pub(crate) struct HttpRequestPool(RefCell<Vec<Rc<HttpRequestInner>>>);
|
||||
|
||||
impl HttpRequestPool {
|
||||
/// Allocates a slab of memory for pool use.
|
||||
pub(crate) fn create() -> &'static HttpRequestPool {
|
||||
let pool = HttpRequestPool(RefCell::new(Vec::with_capacity(128)));
|
||||
Box::leak(Box::new(pool))
|
||||
}
|
||||
|
||||
/// Get message from the pool
|
||||
/// Re-use a previously allocated (but now completed/discarded) HttpRequest object.
|
||||
#[inline]
|
||||
pub(crate) fn get_request(&self) -> Option<HttpRequest> {
|
||||
if let Some(inner) = self.0.borrow_mut().pop() {
|
||||
Some(HttpRequest(inner))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
self.0.borrow_mut().pop().map(HttpRequest)
|
||||
}
|
||||
|
||||
/// Clears all allocated HttpRequest objects.
|
||||
pub(crate) fn clear(&self) {
|
||||
self.0.borrow_mut().clear()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user