Skip to content

Commit e8c97af

Browse files
committed
chore: drop pin-project-lite
Actually we don't need this, all our nested types fall roughly into three categories: - **no perf critical:** Use `Box::pin` to create a new allocation `Pin<Box<T>>` - **already alloated:** They where already wrapped in a `Box<T>` (e.g. for enums with vastly different variants), so `Pin<Box<T>>` is the same overhead. - **`Unpin`:** Some upstream types implement `Unpin`, so you can just use `Pin::new(&mut x)`.
1 parent fad1a83 commit e8c97af

File tree

5 files changed

+108
-126
lines changed

5 files changed

+108
-126
lines changed

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ futures = "0.3"
2828
integer-encoding = "4"
2929
lz4 = { version = "1.23", optional = true }
3030
parking_lot = "0.12"
31-
pin-project-lite = "0.2"
3231
rand = "0.8"
3332
rustls = { version = "0.23", optional = true, default-features = false, features = ["logging", "ring", "std", "tls12"] }
3433
snap = { version = "1", optional = true }

benches/throughput.rs

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@ use chrono::{TimeZone, Utc};
1111
use criterion::{
1212
criterion_group, criterion_main, measurement::WallTime, BenchmarkGroup, Criterion, SamplingMode,
1313
};
14-
use futures::{stream::FuturesUnordered, StreamExt, TryStreamExt};
14+
use futures::{stream::FuturesUnordered, FutureExt, StreamExt, TryStreamExt};
1515
use parking_lot::Once;
16-
use pin_project_lite::pin_project;
1716
use rdkafka::{
1817
consumer::{Consumer, StreamConsumer as RdStreamConsumer},
1918
producer::{FutureProducer, FutureRecord},
@@ -256,17 +255,14 @@ where
256255
fn time_it(self) -> Self::TimeItFut {
257256
TimeIt {
258257
t_start: Instant::now(),
259-
inner: self,
258+
inner: Box::pin(self),
260259
}
261260
}
262261
}
263262

264-
pin_project! {
265-
struct TimeIt<F> {
266-
t_start: Instant,
267-
#[pin]
268-
inner: F,
269-
}
263+
struct TimeIt<F> {
264+
t_start: Instant,
265+
inner: Pin<Box<F>>,
270266
}
271267

272268
impl<F> Future for TimeIt<F>
@@ -275,10 +271,9 @@ where
275271
{
276272
type Output = Duration;
277273

278-
fn poll(self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
279-
let this = self.project();
280-
match this.inner.poll(cx) {
281-
Poll::Ready(_) => Poll::Ready(this.t_start.elapsed()),
274+
fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> {
275+
match self.inner.poll_unpin(cx) {
276+
Poll::Ready(_) => Poll::Ready(self.t_start.elapsed()),
282277
Poll::Pending => Poll::Pending,
283278
}
284279
}

fuzz/fuzz_targets/protocol_reader.rs

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
#![no_main]
2-
use std::{collections::HashMap, io::Cursor, sync::Arc, time::Duration};
2+
use std::{
3+
collections::HashMap,
4+
io::Cursor,
5+
ops::DerefMut,
6+
pin::Pin,
7+
sync::Arc,
8+
task::{Context, Poll},
9+
time::Duration,
10+
};
311

412
use libfuzzer_sys::fuzz_target;
5-
use pin_project_lite::pin_project;
613
use rskafka::{
714
build_info::DEFAULT_CLIENT_ID,
815
messenger::Messenger,
@@ -151,16 +158,12 @@ where
151158
})
152159
}
153160

154-
pin_project! {
155-
/// One-way mock transport with limited data.
156-
///
157-
/// Can only be read. Writes go to `/dev/null`.
158-
struct MockTransport {
159-
#[pin]
160-
data: Cursor<Vec<u8>>,
161-
#[pin]
162-
sink: Sink,
163-
}
161+
/// One-way mock transport with limited data.
162+
///
163+
/// Can only be read. Writes go to `/dev/null`.
164+
struct MockTransport {
165+
data: Cursor<Vec<u8>>,
166+
sink: Sink,
164167
}
165168

166169
impl MockTransport {
@@ -174,34 +177,34 @@ impl MockTransport {
174177

175178
impl AsyncWrite for MockTransport {
176179
fn poll_write(
177-
self: std::pin::Pin<&mut Self>,
178-
cx: &mut std::task::Context<'_>,
180+
mut self: Pin<&mut Self>,
181+
cx: &mut Context<'_>,
179182
buf: &[u8],
180-
) -> std::task::Poll<Result<usize, std::io::Error>> {
181-
self.project().sink.poll_write(cx, buf)
183+
) -> Poll<Result<usize, std::io::Error>> {
184+
Pin::new(&mut self.deref_mut().sink).poll_write(cx, buf)
182185
}
183186

184187
fn poll_flush(
185-
self: std::pin::Pin<&mut Self>,
186-
cx: &mut std::task::Context<'_>,
187-
) -> std::task::Poll<Result<(), std::io::Error>> {
188-
self.project().sink.poll_flush(cx)
188+
mut self: Pin<&mut Self>,
189+
cx: &mut Context<'_>,
190+
) -> Poll<Result<(), std::io::Error>> {
191+
Pin::new(&mut self.deref_mut().sink).poll_flush(cx)
189192
}
190193

191194
fn poll_shutdown(
192-
self: std::pin::Pin<&mut Self>,
193-
cx: &mut std::task::Context<'_>,
194-
) -> std::task::Poll<Result<(), std::io::Error>> {
195-
self.project().sink.poll_shutdown(cx)
195+
mut self: Pin<&mut Self>,
196+
cx: &mut Context<'_>,
197+
) -> Poll<Result<(), std::io::Error>> {
198+
Pin::new(&mut self.deref_mut().sink).poll_shutdown(cx)
196199
}
197200
}
198201

199202
impl AsyncRead for MockTransport {
200203
fn poll_read(
201-
self: std::pin::Pin<&mut Self>,
202-
cx: &mut std::task::Context<'_>,
204+
mut self: Pin<&mut Self>,
205+
cx: &mut Context<'_>,
203206
buf: &mut tokio::io::ReadBuf<'_>,
204-
) -> std::task::Poll<std::io::Result<()>> {
205-
self.project().data.poll_read(cx, buf)
207+
) -> Poll<std::io::Result<()>> {
208+
Pin::new(&mut self.deref_mut().data).poll_read(cx, buf)
206209
}
207210
}

src/client/consumer.rs

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ use std::time::Duration;
5050

5151
use futures::future::{BoxFuture, Fuse, FusedFuture, FutureExt};
5252
use futures::Stream;
53-
use pin_project_lite::pin_project;
5453
use tracing::{debug, trace, warn};
5554

5655
use crate::{
@@ -196,61 +195,58 @@ impl FetchClient for PartitionClient {
196195
}
197196
}
198197

199-
pin_project! {
200-
/// Stream consuming data from start offset.
201-
///
202-
/// # Error Handling
203-
/// If an error is returned by [`fetch_records`](`FetchClient::fetch_records`) then the stream will emit this error
204-
/// once and will terminate afterwards.
205-
pub struct StreamConsumer {
206-
client: Arc<dyn FetchClient>,
198+
/// Stream consuming data from start offset.
199+
///
200+
/// # Error Handling
201+
/// If an error is returned by [`fetch_records`](`PartitionClient::fetch_records`) then the stream will emit this error
202+
/// once and will terminate afterwards.
203+
pub struct StreamConsumer {
204+
client: Arc<dyn FetchClient>,
207205

208-
min_batch_size: i32,
206+
min_batch_size: i32,
209207

210-
max_batch_size: i32,
208+
max_batch_size: i32,
211209

212-
max_wait_ms: i32,
210+
max_wait_ms: i32,
213211

214-
start_offset: StartOffset,
212+
start_offset: StartOffset,
215213

216-
next_offset: Option<i64>,
214+
next_offset: Option<i64>,
217215

218-
next_backoff: Option<Duration>,
216+
next_backoff: Option<Duration>,
219217

220-
terminated: bool,
218+
terminated: bool,
221219

222-
last_high_watermark: i64,
220+
last_high_watermark: i64,
223221

224-
buffer: VecDeque<RecordAndOffset>,
222+
buffer: VecDeque<RecordAndOffset>,
225223

226-
fetch_fut: Fuse<BoxFuture<'static, FetchResult>>,
227-
}
224+
fetch_fut: Fuse<BoxFuture<'static, FetchResult>>,
228225
}
229226

230227
impl Stream for StreamConsumer {
231228
type Item = Result<(RecordAndOffset, i64)>;
232229

233-
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
234-
let this = self.project();
230+
fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
235231
loop {
236-
if *this.terminated {
232+
if self.terminated {
237233
return Poll::Ready(None);
238234
}
239-
if let Some(x) = this.buffer.pop_front() {
240-
return Poll::Ready(Some(Ok((x, *this.last_high_watermark))));
235+
if let Some(x) = self.buffer.pop_front() {
236+
return Poll::Ready(Some(Ok((x, self.last_high_watermark))));
241237
}
242238

243-
if this.fetch_fut.is_terminated() {
244-
let next_offset = *this.next_offset;
245-
let start_offset = *this.start_offset;
246-
let bytes = (*this.min_batch_size)..(*this.max_batch_size);
247-
let max_wait_ms = *this.max_wait_ms;
248-
let next_backoff = std::mem::take(this.next_backoff);
249-
let client = Arc::clone(this.client);
239+
if self.fetch_fut.is_terminated() {
240+
let next_offset = self.next_offset;
241+
let start_offset = self.start_offset;
242+
let bytes = (self.min_batch_size)..(self.max_batch_size);
243+
let max_wait_ms = self.max_wait_ms;
244+
let next_backoff = std::mem::take(&mut self.next_backoff);
245+
let client = Arc::clone(&self.client);
250246

251247
trace!(?start_offset, ?next_offset, "Fetching records at offset");
252248

253-
*this.fetch_fut = FutureExt::fuse(Box::pin(async move {
249+
self.fetch_fut = FutureExt::fuse(Box::pin(async move {
254250
if let Some(backoff) = next_backoff {
255251
tokio::time::sleep(backoff).await;
256252
}
@@ -282,9 +278,9 @@ impl Stream for StreamConsumer {
282278
}));
283279
}
284280

285-
let data: FetchResult = futures::ready!(this.fetch_fut.poll_unpin(cx));
281+
let data: FetchResult = futures::ready!(self.fetch_fut.poll_unpin(cx));
286282

287-
match (data, *this.start_offset) {
283+
match (data, self.start_offset) {
288284
(Ok(inner), _) => {
289285
let FetchResultOk {
290286
mut records_and_offsets,
@@ -300,14 +296,14 @@ impl Stream for StreamConsumer {
300296
// Remember used offset (might be overwritten if there was any data) so we don't refetch the
301297
// earliest / latest offset for every try. Also fetching the latest offset might be racy otherwise,
302298
// since we'll never be in a position where the latest one can actually be fetched.
303-
*this.next_offset = Some(used_offset);
299+
self.next_offset = Some(used_offset);
304300

305301
// Sort records by offset in case they aren't in order
306302
records_and_offsets.sort_by_key(|x| x.offset);
307-
*this.last_high_watermark = watermark;
303+
self.last_high_watermark = watermark;
308304
if let Some(x) = records_and_offsets.last() {
309-
*this.next_offset = Some(x.offset + 1);
310-
this.buffer.extend(records_and_offsets)
305+
self.next_offset = Some(x.offset + 1);
306+
self.buffer.extend(records_and_offsets)
311307
}
312308
continue;
313309
}
@@ -320,25 +316,25 @@ impl Stream for StreamConsumer {
320316
StartOffset::Earliest | StartOffset::Latest,
321317
) => {
322318
// wipe offset and try again
323-
*this.next_offset = None;
319+
self.next_offset = None;
324320

325321
// This will only happen if retention / deletions happen after we've asked for the earliest/latest
326322
// offset and our "fetch" request. This should be a rather rare event, but if something is horrible
327323
// wrong in our cluster (e.g. some actor is spamming "delete" requests) then let's at least backoff
328324
// a bit.
329325
let backoff_secs = 1;
330326
warn!(
331-
start_offset=?this.start_offset,
327+
start_offset=?self.start_offset,
332328
backoff_secs,
333329
"Records are gone between ListOffsets and Fetch, backoff a bit",
334330
);
335-
*this.next_backoff = Some(Duration::from_secs(backoff_secs));
331+
self.next_backoff = Some(Duration::from_secs(backoff_secs));
336332

337333
continue;
338334
}
339335
// if we have an offset, terminate the stream
340336
(Err(e), _) => {
341-
*this.terminated = true;
337+
self.terminated = true;
342338

343339
// report error once
344340
return Poll::Ready(Some(Err(e)));

0 commit comments

Comments
 (0)