From 94da08f506c822064e37d7848f0b0f31b7df9a0e Mon Sep 17 00:00:00 2001 From: Rob Ede Date: Mon, 24 Feb 2020 20:58:41 +0000 Subject: [PATCH] increase content-length fast path to responses up to 1MB --- actix-http/benches/content-length.rs | 32 ++++++++++++++++- actix-http/src/helpers.rs | 54 ++++++++++++++++++++++++++-- 2 files changed, 82 insertions(+), 4 deletions(-) diff --git a/actix-http/benches/content-length.rs b/actix-http/benches/content-length.rs index 150f48a2c..b001b3931 100644 --- a/actix-http/benches/content-length.rs +++ b/actix-http/benches/content-length.rs @@ -67,7 +67,7 @@ mod _new { bytes.put_u8(DIGITS_START + d100); bytes.put_u8(DIGITS_START + d10); bytes.put_u8(DIGITS_START + d1); - } else if n < 10000 { + } else if n < 10_000 { let n = n as u16; let d1000 = (n / 1000) as u8; @@ -75,6 +75,36 @@ mod _new { let d10 = ((n / 10) % 10) as u8; let d1 = (n % 10) as u8; + bytes.put_u8(DIGITS_START + d1000); + bytes.put_u8(DIGITS_START + d100); + bytes.put_u8(DIGITS_START + d10); + bytes.put_u8(DIGITS_START + d1); + } else if n < 100_000 { + let n = n as u32; + + let d10000 = (n / 10000) as u8; + let d1000 = ((n / 1000) % 10) as u8; + let d100 = ((n / 100) % 10) as u8; + let d10 = ((n / 10) % 10) as u8; + let d1 = (n % 10) as u8; + + bytes.put_u8(DIGITS_START + d10000); + bytes.put_u8(DIGITS_START + d1000); + bytes.put_u8(DIGITS_START + d100); + bytes.put_u8(DIGITS_START + d10); + bytes.put_u8(DIGITS_START + d1); + } else if n < 1_000_000 { + let n = n as u32; + + let d100000 = (n / 100000) as u8; + let d10000 = ((n / 10000) % 10) as u8; + let d1000 = ((n / 1000) % 10) as u8; + let d100 = ((n / 100) % 10) as u8; + let d10 = ((n / 10) % 10) as u8; + let d1 = (n % 10) as u8; + + bytes.put_u8(DIGITS_START + d100000); + bytes.put_u8(DIGITS_START + d10000); bytes.put_u8(DIGITS_START + d1000); bytes.put_u8(DIGITS_START + d100); bytes.put_u8(DIGITS_START + d10); diff --git a/actix-http/src/helpers.rs b/actix-http/src/helpers.rs index cba21ed0c..6599f6a32 100644 --- a/actix-http/src/helpers.rs +++ b/actix-http/src/helpers.rs @@ -88,7 +88,7 @@ pub fn write_content_length(n: usize, bytes: &mut BytesMut) { bytes.put_u8(DIGITS_START + d100); bytes.put_u8(DIGITS_START + d10); bytes.put_u8(DIGITS_START + d1); - } else if n < 10000 { + } else if n < 10_000 { let n = n as u16; let d1000 = (n / 1000) as u8; @@ -96,6 +96,36 @@ pub fn write_content_length(n: usize, bytes: &mut BytesMut) { let d10 = ((n / 10) % 10) as u8; let d1 = (n % 10) as u8; + bytes.put_u8(DIGITS_START + d1000); + bytes.put_u8(DIGITS_START + d100); + bytes.put_u8(DIGITS_START + d10); + bytes.put_u8(DIGITS_START + d1); + } else if n < 100_000 { + let n = n as u32; + + let d10000 = (n / 10000) as u8; + let d1000 = ((n / 1000) % 10) as u8; + let d100 = ((n / 100) % 10) as u8; + let d10 = ((n / 10) % 10) as u8; + let d1 = (n % 10) as u8; + + bytes.put_u8(DIGITS_START + d10000); + bytes.put_u8(DIGITS_START + d1000); + bytes.put_u8(DIGITS_START + d100); + bytes.put_u8(DIGITS_START + d10); + bytes.put_u8(DIGITS_START + d1); + } else if n < 1_000_000 { + let n = n as u32; + + let d100000 = (n / 100000) as u8; + let d10000 = ((n / 10000) % 10) as u8; + let d1000 = ((n / 1000) % 10) as u8; + let d100 = ((n / 100) % 10) as u8; + let d10 = ((n / 10) % 10) as u8; + let d1 = (n % 10) as u8; + + bytes.put_u8(DIGITS_START + d100000); + bytes.put_u8(DIGITS_START + d10000); bytes.put_u8(DIGITS_START + d1000); bytes.put_u8(DIGITS_START + d100); bytes.put_u8(DIGITS_START + d10); @@ -109,7 +139,7 @@ pub fn write_content_length(n: usize, bytes: &mut BytesMut) { pub(crate) fn write_usize(n: usize, bytes: &mut BytesMut) { let mut n = n; - + // 20 chars is max length of a usize (2^64) // digits will be added to the buffer from lsd to msd let mut buf = BytesMut::with_capacity(20); @@ -126,7 +156,7 @@ pub(crate) fn write_usize(n: usize, bytes: &mut BytesMut) { // put msd to result buffer bytes.put_u8(DIGITS_START + (n as u8)); - + // put, in reverse (msd to lsd), remaining digits to buffer for i in (0..buf.len()).rev() { bytes.put_u8(buf[i]); @@ -195,11 +225,17 @@ mod tests { write_content_length(5909, &mut bytes); assert_eq!(bytes.split().freeze(), b"\r\ncontent-length: 5909\r\n"[..]); bytes.reserve(50); + write_content_length(9999, &mut bytes); + assert_eq!(bytes.split().freeze(), b"\r\ncontent-length: 9999\r\n"[..]); + bytes.reserve(50); write_content_length(10001, &mut bytes); assert_eq!(bytes.split().freeze(), b"\r\ncontent-length: 10001\r\n"[..]); bytes.reserve(50); write_content_length(59094, &mut bytes); assert_eq!(bytes.split().freeze(), b"\r\ncontent-length: 59094\r\n"[..]); + bytes.reserve(50); + write_content_length(99999, &mut bytes); + assert_eq!(bytes.split().freeze(), b"\r\ncontent-length: 99999\r\n"[..]); bytes.reserve(50); write_content_length(590947, &mut bytes); @@ -208,6 +244,12 @@ mod tests { b"\r\ncontent-length: 590947\r\n"[..] ); bytes.reserve(50); + write_content_length(999999, &mut bytes); + assert_eq!( + bytes.split().freeze(), + b"\r\ncontent-length: 999999\r\n"[..] + ); + bytes.reserve(50); write_content_length(5909471, &mut bytes); assert_eq!( bytes.split().freeze(), @@ -219,5 +261,11 @@ mod tests { bytes.split().freeze(), b"\r\ncontent-length: 59094718\r\n"[..] ); + bytes.reserve(50); + write_content_length(4294973728, &mut bytes); + assert_eq!( + bytes.split().freeze(), + b"\r\ncontent-length: 4294973728\r\n"[..] + ); } }