@@ -20,9 +20,6 @@ use super::{
2020 TPCH_QUERY_START_ID , TPCH_TABLES ,
2121} ;
2222use async_trait:: async_trait;
23- use std:: path:: PathBuf ;
24- use std:: sync:: Arc ;
25-
2623use datafusion:: arrow:: record_batch:: RecordBatch ;
2724use datafusion:: arrow:: util:: pretty:: { self , pretty_format_batches} ;
2825use datafusion:: common:: instant:: Instant ;
@@ -40,18 +37,25 @@ use datafusion::execution::{SessionState, SessionStateBuilder};
4037use datafusion:: physical_plan:: display:: DisplayableExecutionPlan ;
4138use datafusion:: physical_plan:: { collect, displayable} ;
4239use datafusion:: prelude:: * ;
40+ use datafusion_distributed:: MappedDistributedSessionBuilderExt ;
41+ use std:: path:: PathBuf ;
42+ use std:: sync:: Arc ;
4343
4444use crate :: util:: {
4545 BenchmarkRun , CommonOpt , InMemoryCacheExecCodec , InMemoryDataSourceRule , QueryResult ,
4646 WarmingUpMarker ,
4747} ;
48- use datafusion_distributed:: test_utils:: localhost:: start_localhost_context;
48+ use datafusion_distributed:: test_utils:: localhost:: {
49+ get_free_ports, spawn_flight_service, start_localhost_context, LocalHostChannelResolver ,
50+ } ;
4951use datafusion_distributed:: {
5052 DistributedExt , DistributedPhysicalOptimizerRule , DistributedSessionBuilder ,
5153 DistributedSessionBuilderContext ,
5254} ;
5355use log:: info;
5456use structopt:: StructOpt ;
57+ use tokio:: net:: TcpListener ;
58+ use tokio:: task:: JoinHandle ;
5559
5660// hack to avoid `default_value is meaningless for bool` errors
5761type BoolDefaultTrue = bool ;
@@ -113,6 +117,14 @@ pub struct RunOpt {
113117 /// Number of partitions per task.
114118 #[ structopt( long = "ppt" ) ]
115119 partitions_per_task : Option < usize > ,
120+
121+ /// Number of physical threads per worker (default 1)
122+ #[ structopt( long, default_value = "1" ) ]
123+ workers : usize ,
124+
125+ /// Number of physical threads per worker
126+ #[ structopt( long) ]
127+ threads : Option < usize > ,
116128}
117129
118130#[ async_trait]
@@ -156,7 +168,50 @@ impl DistributedSessionBuilder for RunOpt {
156168}
157169
158170impl RunOpt {
159- pub async fn run ( mut self ) -> Result < ( ) > {
171+ pub fn spawn_workers ( self ) -> Vec < ( tokio:: runtime:: Runtime , JoinHandle < ( ) > ) > {
172+ let ports = get_free_ports ( self . workers ) ;
173+ let channel_resolver = LocalHostChannelResolver :: new ( ports. clone ( ) ) ;
174+ let threads_per_worker = self . threads ;
175+ let session_builder = self . map ( move |builder : SessionStateBuilder | {
176+ let channel_resolver = channel_resolver. clone ( ) ;
177+ Ok ( builder
178+ . with_distributed_channel_resolver ( channel_resolver)
179+ . build ( ) )
180+ } ) ;
181+ let mut handles = vec ! [ ] ;
182+ for port in ports {
183+ let session_builder = session_builder. clone ( ) ;
184+ let rt = tokio:: runtime:: Builder :: new_multi_thread ( )
185+ . worker_threads ( threads_per_worker. unwrap_or ( get_available_parallelism ( ) ) )
186+ . enable_all ( )
187+ . build ( )
188+ . unwrap ( ) ;
189+ let handle = rt. spawn ( async move {
190+ let listener = TcpListener :: bind ( format ! ( "127.0.0.1:{port}" ) )
191+ . await
192+ . unwrap ( ) ;
193+ spawn_flight_service ( session_builder, listener)
194+ . await
195+ . unwrap ( ) ;
196+ } ) ;
197+
198+ handles. push ( ( rt, handle) ) ;
199+ }
200+ handles
201+ }
202+
203+ pub fn run ( self ) -> Result < ( ) > {
204+ let _handle = self . clone ( ) . spawn_workers ( ) ;
205+
206+ let rt = tokio:: runtime:: Builder :: new_multi_thread ( )
207+ . worker_threads ( self . threads . unwrap_or ( get_available_parallelism ( ) ) )
208+ . enable_all ( )
209+ . build ( ) ?;
210+
211+ rt. block_on ( async move { self . _run ( ) . await } )
212+ }
213+
214+ pub async fn _run ( mut self ) -> Result < ( ) > {
160215 let ( ctx, _guard) = start_localhost_context ( 1 , self . clone ( ) ) . await ;
161216 println ! ( "Running benchmarks with the following options: {self:?}" ) ;
162217 let query_range = match self . query {
0 commit comments