Skip to content

Commit 634d24a

Browse files
committed
Wrap Builder in an Arc
The builder ends up being cloned a couple of times per connection, so use Arc::get_mut to make that faster.
1 parent 540bcc5 commit 634d24a

4 files changed

Lines changed: 35 additions & 17 deletions

File tree

tokio-postgres/src/builder.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::iter;
33
#[cfg(all(feature = "runtime", unix))]
44
use std::path::{Path, PathBuf};
55
use std::str::{self, FromStr};
6+
use std::sync::Arc;
67
#[cfg(feature = "runtime")]
78
use std::time::Duration;
89
use tokio_io::{AsyncRead, AsyncWrite};
@@ -23,7 +24,7 @@ pub(crate) enum Host {
2324
}
2425

2526
#[derive(Debug, Clone, PartialEq)]
26-
pub struct Builder {
27+
pub(crate) struct Inner {
2728
pub(crate) params: HashMap<String, String>,
2829
pub(crate) password: Option<Vec<u8>>,
2930
#[cfg(feature = "runtime")]
@@ -34,6 +35,9 @@ pub struct Builder {
3435
pub(crate) connect_timeout: Option<Duration>,
3536
}
3637

38+
#[derive(Debug, Clone, PartialEq)]
39+
pub struct Builder(pub(crate) Arc<Inner>);
40+
3741
impl Default for Builder {
3842
fn default() -> Builder {
3943
Builder::new()
@@ -46,7 +50,7 @@ impl Builder {
4650
params.insert("client_encoding".to_string(), "UTF8".to_string());
4751
params.insert("timezone".to_string(), "GMT".to_string());
4852

49-
Builder {
53+
Builder(Arc::new(Inner {
5054
params,
5155
password: None,
5256
#[cfg(feature = "runtime")]
@@ -55,20 +59,24 @@ impl Builder {
5559
port: vec![],
5660
#[cfg(feature = "runtime")]
5761
connect_timeout: None,
58-
}
62+
}))
5963
}
6064

6165
#[cfg(feature = "runtime")]
6266
pub fn host(&mut self, host: &str) -> &mut Builder {
6367
#[cfg(unix)]
6468
{
6569
if host.starts_with('/') {
66-
self.host.push(Host::Unix(PathBuf::from(host)));
70+
Arc::make_mut(&mut self.0)
71+
.host
72+
.push(Host::Unix(PathBuf::from(host)));
6773
return self;
6874
}
6975
}
7076

71-
self.host.push(Host::Tcp(host.to_string()));
77+
Arc::make_mut(&mut self.0)
78+
.host
79+
.push(Host::Tcp(host.to_string()));
7280
self
7381
}
7482

@@ -77,32 +85,36 @@ impl Builder {
7785
where
7886
T: AsRef<Path>,
7987
{
80-
self.host.push(Host::Unix(host.as_ref().to_path_buf()));
88+
Arc::make_mut(&mut self.0)
89+
.host
90+
.push(Host::Unix(host.as_ref().to_path_buf()));
8191
self
8292
}
8393

8494
#[cfg(feature = "runtime")]
8595
pub fn port(&mut self, port: u16) -> &mut Builder {
86-
self.port.push(port);
96+
Arc::make_mut(&mut self.0).port.push(port);
8797
self
8898
}
8999

90100
#[cfg(feature = "runtime")]
91101
pub fn connect_timeout(&mut self, connect_timeout: Duration) -> &mut Builder {
92-
self.connect_timeout = Some(connect_timeout);
102+
Arc::make_mut(&mut self.0).connect_timeout = Some(connect_timeout);
93103
self
94104
}
95105

96106
pub fn password<T>(&mut self, password: T) -> &mut Builder
97107
where
98108
T: AsRef<[u8]>,
99109
{
100-
self.password = Some(password.as_ref().to_vec());
110+
Arc::make_mut(&mut self.0).password = Some(password.as_ref().to_vec());
101111
self
102112
}
103113

104114
pub fn param(&mut self, key: &str, value: &str) -> &mut Builder {
105-
self.params.insert(key.to_string(), value.to_string());
115+
Arc::make_mut(&mut self.0)
116+
.params
117+
.insert(key.to_string(), value.to_string());
106118
self
107119
}
108120

tokio-postgres/src/proto/connect.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,15 @@ where
3838
fn poll_start<'a>(state: &'a mut RentToOwn<'a, Start<T>>) -> Poll<AfterStart<T>, Error> {
3939
let mut state = state.take();
4040

41-
if state.config.host.is_empty() {
41+
if state.config.0.host.is_empty() {
4242
return Err(Error::missing_host());
4343
}
4444

45-
if state.config.port.len() > 1 && state.config.port.len() != state.config.host.len() {
45+
if state.config.0.port.len() > 1 && state.config.0.port.len() != state.config.0.host.len() {
4646
return Err(Error::invalid_port_count());
4747
}
4848

49-
let hostname = match &state.config.host[0] {
49+
let hostname = match &state.config.0.host[0] {
5050
Host::Tcp(host) => &**host,
5151
// postgres doesn't support TLS over unix sockets, so the choice here doesn't matter
5252
#[cfg(unix)]
@@ -86,7 +86,7 @@ where
8686
let mut state = state.take();
8787
let idx = state.idx + 1;
8888

89-
let host = match state.config.host.get(idx) {
89+
let host = match state.config.0.host.get(idx) {
9090
Some(host) => host,
9191
None => return Err(e),
9292
};

tokio-postgres/src/proto/connect_once.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,19 @@ where
7878

7979
let port = *state
8080
.config
81+
.0
8182
.port
8283
.get(state.idx)
83-
.or_else(|| state.config.port.get(0))
84+
.or_else(|| state.config.0.port.get(0))
8485
.unwrap_or(&5432);
8586

8687
let timeout = state
8788
.config
89+
.0
8890
.connect_timeout
8991
.map(|d| Delay::new(Instant::now() + d));
9092

91-
match &state.config.host[state.idx] {
93+
match &state.config.0.host[state.idx] {
9294
Host::Tcp(host) => {
9395
let host = host.clone();
9496
transition!(ResolvingDns {

tokio-postgres/src/proto/handshake.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ where
7979

8080
let mut buf = vec![];
8181
frontend::startup_message(
82-
state.config.params.iter().map(|(k, v)| {
82+
state.config.0.params.iter().map(|(k, v)| {
8383
// libpq uses dbname, but the backend expects database (!)
8484
let k = if k == "dbname" { "database" } else { &**k };
8585
(k, &**v)
@@ -124,6 +124,7 @@ where
124124
Some(Message::AuthenticationCleartextPassword) => {
125125
let pass = state
126126
.config
127+
.0
127128
.password
128129
.as_ref()
129130
.ok_or_else(Error::missing_password)?;
@@ -136,11 +137,13 @@ where
136137
Some(Message::AuthenticationMd5Password(body)) => {
137138
let user = state
138139
.config
140+
.0
139141
.params
140142
.get("user")
141143
.ok_or_else(Error::missing_user)?;
142144
let pass = state
143145
.config
146+
.0
144147
.password
145148
.as_ref()
146149
.ok_or_else(Error::missing_password)?;
@@ -154,6 +157,7 @@ where
154157
Some(Message::AuthenticationSasl(body)) => {
155158
let pass = state
156159
.config
160+
.0
157161
.password
158162
.as_ref()
159163
.ok_or_else(Error::missing_password)?;

0 commit comments

Comments
 (0)