15
15
use std:: {
16
16
sync:: {
17
17
atomic:: { AtomicUsize , Ordering } ,
18
- mpsc:: { channel, SendError , Sender , TryRecvError } ,
19
18
Arc ,
20
19
} ,
21
20
thread:: { self , JoinHandle } ,
22
21
} ;
23
22
24
23
use chrono:: { TimeZone , Utc } ;
24
+ use crossbeam:: queue:: SegQueue ;
25
25
use profiling:: data_export:: common:: FieldValue as WitFieldValue ;
26
26
use profiling:: data_export:: measurement:: Point ;
27
27
use profiling:: data_export:: metric:: Sample ;
@@ -49,7 +49,7 @@ wasmtime::component::bindgen!({
49
49
pub struct DataExporter {
50
50
bytes_len : Arc < AtomicUsize > ,
51
51
bytes_watermark : usize ,
52
- data_tx : Option < Sender < Data > > ,
52
+ data_queue : Arc < SegQueue < Option < Data > > > ,
53
53
exporter : JoinHandle < ( ) > ,
54
54
}
55
55
@@ -63,22 +63,23 @@ impl DataExporter {
63
63
// TODO: `bytes_capacity` is not used because we not have a static allocation
64
64
// for `Data`, maybe we will remove this in the future
65
65
let _ = bytes_capacity;
66
- let ( data_tx , data_rx ) = channel :: < Data > ( ) ;
66
+ let data_queue = Arc :: new ( SegQueue :: < Option < Data > > :: new ( ) ) ;
67
67
let bytes_len = Arc :: new ( AtomicUsize :: new ( 0 ) ) ;
68
68
69
69
let exporter = thread:: spawn ( {
70
+ let data_queue = Arc :: clone ( & data_queue) ;
70
71
let bytes_len = Arc :: clone ( & bytes_len) ;
71
72
move || {
72
73
let rt = Runtime :: new ( ) . expect ( "Failed to init exporter runtime" ) ;
73
74
let mut data = Vec :: new ( ) ;
74
75
loop {
75
- match data_rx . try_recv ( ) {
76
- Ok ( o ) => {
76
+ match data_queue . pop ( ) {
77
+ Some ( Some ( o ) ) => {
77
78
// No critical section, relaxed ordering is fine.
78
79
bytes_len. fetch_sub ( o. encoded_len ( ) , Ordering :: Relaxed ) ;
79
80
data. push ( o) ;
80
81
}
81
- Err ( e ) => {
82
+ poped => {
82
83
if !data. is_empty ( ) {
83
84
let merged = ExportDataReq {
84
85
task_id : task_id. clone ( ) ,
@@ -91,9 +92,10 @@ impl DataExporter {
91
92
} ) ;
92
93
data. clear ( ) ;
93
94
}
94
- match e {
95
- TryRecvError :: Empty => thread:: park ( ) ,
96
- TryRecvError :: Disconnected => break ,
95
+ match poped {
96
+ None => thread:: park ( ) ,
97
+ Some ( None ) => break ,
98
+ _ => unreachable ! ( ) ,
97
99
}
98
100
}
99
101
}
@@ -104,7 +106,7 @@ impl DataExporter {
104
106
Self {
105
107
bytes_len,
106
108
bytes_watermark,
107
- data_tx : Some ( data_tx ) ,
109
+ data_queue ,
108
110
exporter,
109
111
}
110
112
}
@@ -113,24 +115,21 @@ impl DataExporter {
113
115
self . exporter . thread ( ) . unpark ( ) ;
114
116
}
115
117
116
- pub fn schedule ( & self , data : Data ) -> Result < ( ) , SendError < Data > > {
118
+ pub fn schedule ( & self , data : Data ) {
117
119
let encoded_len = data. encoded_len ( ) ;
118
- // Never failes since we only take it in `Drop`.
119
- let data_tx = self . data_tx . as_ref ( ) . expect ( "unreachable" ) ;
120
- data_tx. send ( data) ?;
120
+ self . data_queue . push ( Some ( data) ) ;
121
121
// No critical section, relaxed ordering is fine.
122
122
let prev = self . bytes_len . fetch_add ( encoded_len, Ordering :: Relaxed ) ;
123
123
if prev > self . bytes_watermark {
124
124
self . exporter . thread ( ) . unpark ( ) ;
125
125
}
126
- Ok ( ( ) )
127
126
}
128
127
}
129
128
130
129
impl Drop for DataExporter {
131
130
fn drop ( & mut self ) {
132
- // Drop sender early to prevent the exporter thread from being parked forever .
133
- drop ( self . data_tx . take ( ) ) ;
131
+ // Notify the consumer that there is no more data .
132
+ self . data_queue . push ( None ) ;
134
133
self . exporter . thread ( ) . unpark ( ) ;
135
134
}
136
135
}
@@ -178,7 +177,7 @@ impl profiling::data_export::file::Host for DataExportCtx {
178
177
ty : DataType :: File as _ ,
179
178
bytes,
180
179
} ;
181
- ctx. exporter . schedule ( data) ? ;
180
+ ctx. exporter . schedule ( data) ;
182
181
183
182
Ok ( Ok ( ( ) ) )
184
183
}
@@ -211,7 +210,7 @@ impl profiling::data_export::metric::Host for DataExportCtx {
211
210
ty : DataType :: LineProtocol as _ ,
212
211
bytes,
213
212
} ;
214
- ctx. exporter . schedule ( data) ? ;
213
+ ctx. exporter . schedule ( data) ;
215
214
216
215
Ok ( Ok ( ( ) ) )
217
216
}
@@ -247,7 +246,7 @@ impl profiling::data_export::measurement::Host for DataExportCtx {
247
246
ty : DataType :: LineProtocol as _ ,
248
247
bytes,
249
248
} ;
250
- ctx. exporter . schedule ( data) ? ;
249
+ ctx. exporter . schedule ( data) ;
251
250
252
251
Ok ( Ok ( ( ) ) )
253
252
}
0 commit comments