mirror of
https://github.com/wisdgod/cursor-api.git
synced 2025-10-07 07:31:56 +08:00
perf: optimize
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
# 0.4.12 (August 5, 2025)
|
||||
|
||||
* Fix default limits on max stored reset streams and duration to more reasonable values.
|
||||
|
||||
# 0.4.11 (June 30, 2025)
|
||||
|
||||
* Fix client to not return an error when a clean shutdown otherwise doesn't get a TLS close_notify, which some servers don't bother sending.
|
||||
|
@@ -3,7 +3,7 @@ name = "h2"
|
||||
# When releasing to crates.io:
|
||||
# - Update CHANGELOG.md.
|
||||
# - Create git tag
|
||||
version = "0.4.11"
|
||||
version = "0.4.12"
|
||||
license = "MIT"
|
||||
authors = [
|
||||
"Carl Lerche <me@carllerche.com>",
|
||||
|
@@ -53,19 +53,6 @@ fn main() {
|
||||
|
||||
## FAQ
|
||||
|
||||
**How does h2 compare to [solicit] or [rust-http2]?**
|
||||
|
||||
The h2 library has implemented more of the details of the HTTP/2 specification
|
||||
than any other Rust library. It also passes the [h2spec] set of tests. The h2
|
||||
library is rapidly approaching "production ready" quality.
|
||||
|
||||
Besides the above, Solicit is built on blocking I/O and does not appear to be
|
||||
actively maintained.
|
||||
|
||||
**Is this an embedded Java SQL database engine?**
|
||||
|
||||
[No](https://www.h2database.com).
|
||||
|
||||
[solicit]: https://github.com/mlalic/solicit
|
||||
[rust-http2]: https://github.com/stepancheg/rust-http2
|
||||
[h2spec]: https://github.com/summerwind/h2spec
|
||||
|
@@ -923,7 +923,7 @@ impl Builder {
|
||||
/// received for that stream will result in a connection level protocol
|
||||
/// error, forcing the connection to terminate.
|
||||
///
|
||||
/// The default value is 10.
|
||||
/// The default value is currently 50.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -968,7 +968,7 @@ impl Builder {
|
||||
/// received for that stream will result in a connection level protocol
|
||||
/// error, forcing the connection to terminate.
|
||||
///
|
||||
/// The default value is 30 seconds.
|
||||
/// The default value is currently 1 second.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@@ -33,6 +33,10 @@ pub type WindowSize = u32;
|
||||
pub const MAX_WINDOW_SIZE: WindowSize = (1 << 31) - 1; // i32::MAX as u32
|
||||
pub const DEFAULT_REMOTE_RESET_STREAM_MAX: usize = 20;
|
||||
pub const DEFAULT_LOCAL_RESET_COUNT_MAX: usize = 1024;
|
||||
pub const DEFAULT_RESET_STREAM_MAX: usize = 10;
|
||||
pub const DEFAULT_RESET_STREAM_SECS: u64 = 30;
|
||||
// RFC 9113 suggests allowing at minimum 100 streams, it seems reasonable to
|
||||
// by default allow a portion of that to be remembered as reset for some time.
|
||||
pub const DEFAULT_RESET_STREAM_MAX: usize = 50;
|
||||
// RFC 9113#5.4.2 suggests ~1 RTT. We don't track that closely, but use a
|
||||
// reasonable guess of the average here.
|
||||
pub const DEFAULT_RESET_STREAM_SECS: u64 = 1;
|
||||
pub const DEFAULT_MAX_SEND_BUFFER_SIZE: usize = 1024 * 400;
|
||||
|
@@ -73,3 +73,56 @@ pub struct Config {
|
||||
/// When this gets exceeded, we issue GOAWAYs.
|
||||
pub local_max_error_reset_streams: Option<usize>,
|
||||
}
|
||||
|
||||
trait DebugStructExt<'a, 'b> {
|
||||
// h2_ prefixes to protect against possible future name collisions
|
||||
fn h2_field_if(&mut self, name: &str, val: &bool) -> &mut std::fmt::DebugStruct<'a, 'b>;
|
||||
|
||||
fn h2_field_if_then<T: std::fmt::Debug>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
cond: bool,
|
||||
val: &T,
|
||||
) -> &mut std::fmt::DebugStruct<'a, 'b>;
|
||||
|
||||
fn h2_field_some<T: std::fmt::Debug>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
val: &Option<T>,
|
||||
) -> &mut std::fmt::DebugStruct<'a, 'b>;
|
||||
}
|
||||
|
||||
impl<'a, 'b> DebugStructExt<'a, 'b> for std::fmt::DebugStruct<'a, 'b> {
|
||||
fn h2_field_if(&mut self, name: &str, val: &bool) -> &mut std::fmt::DebugStruct<'a, 'b> {
|
||||
if *val {
|
||||
self.field(name, val)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn h2_field_if_then<T: std::fmt::Debug>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
cond: bool,
|
||||
val: &T,
|
||||
) -> &mut std::fmt::DebugStruct<'a, 'b> {
|
||||
if cond {
|
||||
self.field(name, val)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn h2_field_some<T: std::fmt::Debug>(
|
||||
&mut self,
|
||||
name: &str,
|
||||
val: &Option<T>,
|
||||
) -> &mut std::fmt::DebugStruct<'a, 'b> {
|
||||
if val.is_some() {
|
||||
self.field(name, val)
|
||||
} else {
|
||||
self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -912,11 +912,15 @@ impl Recv {
|
||||
return;
|
||||
}
|
||||
|
||||
tracing::trace!("enqueue_reset_expiration; {:?}", stream.id);
|
||||
|
||||
if counts.can_inc_num_reset_streams() {
|
||||
counts.inc_num_reset_streams();
|
||||
tracing::trace!("enqueue_reset_expiration; added {:?}", stream.id);
|
||||
self.pending_reset_expired.push(stream);
|
||||
} else {
|
||||
tracing::trace!(
|
||||
"enqueue_reset_expiration; dropped {:?}, over max_concurrent_reset_streams",
|
||||
stream.id
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,3 +1,4 @@
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
|
||||
use crate::codec::UserError;
|
||||
@@ -47,7 +48,7 @@ use self::Peer::*;
|
||||
/// ES: END_STREAM flag
|
||||
/// R: RST_STREAM frame
|
||||
/// ```
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct State {
|
||||
inner: Inner,
|
||||
}
|
||||
@@ -465,3 +466,10 @@ impl Default for State {
|
||||
State { inner: Inner::Idle }
|
||||
}
|
||||
}
|
||||
|
||||
// remove some noise for debug output
|
||||
impl fmt::Debug for State {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.inner.fmt(f)
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,6 @@ pub(crate) struct Key {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
struct SlabIndex(u32);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct Queue<N> {
|
||||
indices: Option<store::Indices>,
|
||||
_p: PhantomData<N>,
|
||||
@@ -378,6 +377,15 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<N> fmt::Debug for Queue<N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
f.debug_struct("Queue")
|
||||
.field("indices", &self.indices)
|
||||
// skip phantom data
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
// ===== impl Ptr =====
|
||||
|
||||
impl<'a> Ptr<'a> {
|
||||
|
@@ -398,35 +398,47 @@ impl fmt::Debug for Stream {
|
||||
.field("state", &self.state)
|
||||
.field("is_counted", &self.is_counted)
|
||||
.field("ref_count", &self.ref_count)
|
||||
.field("next_pending_send", &self.next_pending_send)
|
||||
.field("is_pending_send", &self.is_pending_send)
|
||||
.h2_field_some("next_pending_send", &self.next_pending_send)
|
||||
.h2_field_if("is_pending_send", &self.is_pending_send)
|
||||
.field("send_flow", &self.send_flow)
|
||||
.field("requested_send_capacity", &self.requested_send_capacity)
|
||||
.field("buffered_send_data", &self.buffered_send_data)
|
||||
.field("send_task", &self.send_task.as_ref().map(|_| ()))
|
||||
.field("pending_send", &self.pending_send)
|
||||
.field(
|
||||
.h2_field_some("send_task", &self.send_task.as_ref().map(|_| ()))
|
||||
.h2_field_if_then(
|
||||
"pending_send",
|
||||
!self.pending_send.is_empty(),
|
||||
&self.pending_send,
|
||||
)
|
||||
.h2_field_some(
|
||||
"next_pending_send_capacity",
|
||||
&self.next_pending_send_capacity,
|
||||
)
|
||||
.field("is_pending_send_capacity", &self.is_pending_send_capacity)
|
||||
.field("send_capacity_inc", &self.send_capacity_inc)
|
||||
.field("next_open", &self.next_open)
|
||||
.field("is_pending_open", &self.is_pending_open)
|
||||
.field("is_pending_push", &self.is_pending_push)
|
||||
.field("next_pending_accept", &self.next_pending_accept)
|
||||
.field("is_pending_accept", &self.is_pending_accept)
|
||||
.h2_field_if("is_pending_send_capacity", &self.is_pending_send_capacity)
|
||||
.h2_field_if("send_capacity_inc", &self.send_capacity_inc)
|
||||
.h2_field_some("next_open", &self.next_open)
|
||||
.h2_field_if("is_pending_open", &self.is_pending_open)
|
||||
.h2_field_if("is_pending_push", &self.is_pending_push)
|
||||
.h2_field_some("next_pending_accept", &self.next_pending_accept)
|
||||
.h2_field_if("is_pending_accept", &self.is_pending_accept)
|
||||
.field("recv_flow", &self.recv_flow)
|
||||
.field("in_flight_recv_data", &self.in_flight_recv_data)
|
||||
.field("next_window_update", &self.next_window_update)
|
||||
.field("is_pending_window_update", &self.is_pending_window_update)
|
||||
.field("reset_at", &self.reset_at)
|
||||
.field("next_reset_expire", &self.next_reset_expire)
|
||||
.field("pending_recv", &self.pending_recv)
|
||||
.field("is_recv", &self.is_recv)
|
||||
.field("recv_task", &self.recv_task.as_ref().map(|_| ()))
|
||||
.field("push_task", &self.push_task.as_ref().map(|_| ()))
|
||||
.field("pending_push_promises", &self.pending_push_promises)
|
||||
.h2_field_some("next_window_update", &self.next_window_update)
|
||||
.h2_field_if("is_pending_window_update", &self.is_pending_window_update)
|
||||
.h2_field_some("reset_at", &self.reset_at)
|
||||
.h2_field_some("next_reset_expire", &self.next_reset_expire)
|
||||
.h2_field_if_then(
|
||||
"pending_recv",
|
||||
!self.pending_recv.is_empty(),
|
||||
&self.pending_recv,
|
||||
)
|
||||
.h2_field_if("is_recv", &self.is_recv)
|
||||
.h2_field_some("recv_task", &self.recv_task.as_ref().map(|_| ()))
|
||||
.h2_field_some("push_task", &self.push_task.as_ref().map(|_| ()))
|
||||
.h2_field_if_then(
|
||||
"pending_push_promises",
|
||||
!self.pending_push_promises.is_empty(),
|
||||
&self.pending_push_promises,
|
||||
)
|
||||
.field("content_length", &self.content_length)
|
||||
.finish()
|
||||
}
|
||||
|
@@ -868,7 +868,7 @@ impl Builder {
|
||||
/// received for that stream will result in a connection level protocol
|
||||
/// error, forcing the connection to terminate.
|
||||
///
|
||||
/// The default value is 10.
|
||||
/// The default value is currently 50.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -993,7 +993,7 @@ impl Builder {
|
||||
/// received for that stream will result in a connection level protocol
|
||||
/// error, forcing the connection to terminate.
|
||||
///
|
||||
/// The default value is 30 seconds.
|
||||
/// The default value is currently 1 second.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
Reference in New Issue
Block a user