Skip to content

Commit 13327be

Browse files
committed
feat: format logs to fixed buffer to avoid one more allocation
1 parent 97c0952 commit 13327be

File tree

1 file changed

+32
-6
lines changed

1 file changed

+32
-6
lines changed

src/log.rs

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
use std::fmt;
2+
use std::io::Write;
3+
14
/// Utility function to provide typed checking of the mask's field state.
25
#[inline(always)]
36
pub fn check_mask(mask: DebugMask, log_level: usize) -> bool {
@@ -8,6 +11,29 @@ pub fn check_mask(mask: DebugMask, log_level: usize) -> bool {
811
true
912
}
1013

14+
/// Format args into a provided buffer
15+
// XXX: use core::io::BorrowedBuf to avoid initialization when stabilized
16+
// XXX: may produce incomplete UTF-8 sequences. But writes to `ngx_log_t` already can be truncated,
17+
// so nothing we can do here.
18+
#[inline]
19+
pub fn format_into_buf<'a>(args: fmt::Arguments<'_>, out: &'a mut [u8]) -> &'a [u8] {
20+
if let Some(str) = args.as_str() {
21+
str.as_bytes()
22+
} else {
23+
let mut cur = std::io::Cursor::new(out);
24+
// nothing we can or want to do on errors.
25+
let _ = cur.write_fmt(args);
26+
let n = cur.position() as usize;
27+
&cur.into_inner()[..n]
28+
}
29+
}
30+
31+
/// Size of the static buffer used to format log messages.
32+
///
33+
/// Approximates the remaining space in `u_char[NGX_MAX_ERROR_STR]` after writing the standard log
34+
/// prefix (`1970/01/01 00:00:00 [info] 1#1: `).
35+
pub const LOG_BUFFER_SIZE: usize = (crate::ffi::NGX_MAX_ERROR_STR - 32) as _;
36+
1137
/// Write to logger at a specified level.
1238
///
1339
/// See [Logging](https://nginx.org/en/docs/dev/development_guide.html#logging)
@@ -18,8 +44,8 @@ macro_rules! ngx_log_error {
1844
let log = $log;
1945
let level = $level as $crate::ffi::ngx_uint_t;
2046
if level < unsafe { (*log).log_level } {
21-
let message = ::std::format!($($arg)+);
22-
let message = message.as_bytes();
47+
let mut out = [0u8; $crate::log::LOG_BUFFER_SIZE];
48+
let message = $crate::log::format_into_buf(format_args!($($arg)+), &mut out);
2349
unsafe {
2450
$crate::ffi::ngx_log_error_core(level, log, 0, c"%*s".as_ptr(), message.len(), message.as_ptr());
2551
}
@@ -34,8 +60,8 @@ macro_rules! ngx_conf_log_error {
3460
let cf: *mut $crate::ffi::ngx_conf_t = $cf;
3561
let level = $level as $crate::ffi::ngx_uint_t;
3662
if level < unsafe { (*(*cf).log).log_level } {
37-
let message = ::std::format!($($arg)+);
38-
let message = message.as_bytes();
63+
let mut out = [0u8; $crate::log::LOG_BUFFER_SIZE];
64+
let message = $crate::log::format_into_buf(format_args!($($arg)+), &mut out);
3965
unsafe {
4066
$crate::ffi::ngx_conf_log_error(level, cf, 0, c"%*s".as_ptr(), message.len(), message.as_ptr());
4167
}
@@ -50,8 +76,8 @@ macro_rules! ngx_log_debug {
5076
let log = $log;
5177
if $crate::log::check_mask($mask, unsafe { (*log).log_level }) {
5278
let level = $crate::ffi::NGX_LOG_DEBUG as $crate::ffi::ngx_uint_t;
53-
let message = format!($($arg)+);
54-
let message = message.as_bytes();
79+
let mut out = [0u8; $crate::log::LOG_BUFFER_SIZE];
80+
let message = $crate::log::format_into_buf(format_args!($($arg)+), &mut out);
5581
unsafe {
5682
$crate::ffi::ngx_log_error_core(level, log, 0, c"%*s".as_ptr(), message.len(), message.as_ptr());
5783
}

0 commit comments

Comments
 (0)