1515// specific language governing permissions and limitations
1616// under the License.
1717
18- use crate :: execution:: memory_management:: { MemoryConsumer , MemoryConsumerId } ;
19- use crate :: physical_plan:: aggregates:: return_type;
18+ use crate :: execution:: memory_management:: MemoryConsumer ;
2019use hashbrown:: HashMap ;
2120use log:: { info, warn} ;
22- use std:: cmp:: { max, min} ;
21+ use std:: cmp:: min;
22+ use std:: fmt;
23+ use std:: fmt:: { Debug , Formatter } ;
2324use std:: sync:: { Arc , Condvar , Mutex } ;
2425
25- pub ( crate ) trait ExecutionMemoryPool {
26+ pub ( crate ) trait ExecutionMemoryPool : Sync + Send + Debug {
2627 fn memory_available ( & self ) -> usize ;
2728 fn memory_used ( & self ) -> usize ;
2829 fn memory_used_partition ( & self , partition_id : usize ) -> usize ;
29- fn acquire_memory ( & self , required : usize , consumer : & dyn MemoryConsumer ) -> usize ;
30+ fn acquire_memory (
31+ & self ,
32+ required : usize ,
33+ consumer : & Arc < dyn MemoryConsumer > ,
34+ ) -> usize ;
3035 fn update_usage (
3136 & self ,
3237 granted_size : usize ,
@@ -49,6 +54,14 @@ impl DummyExecutionMemoryPool {
4954 }
5055}
5156
57+ impl Debug for DummyExecutionMemoryPool {
58+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
59+ f. debug_struct ( "DummyExecutionMemoryPool" )
60+ . field ( "total" , & self . pool_size )
61+ . finish ( )
62+ }
63+ }
64+
5265impl ExecutionMemoryPool for DummyExecutionMemoryPool {
5366 fn memory_available ( & self ) -> usize {
5467 usize:: MAX
@@ -62,7 +75,11 @@ impl ExecutionMemoryPool for DummyExecutionMemoryPool {
6275 0
6376 }
6477
65- fn acquire_memory ( & self , required : usize , _consumer : & dyn MemoryConsumer ) -> usize {
78+ fn acquire_memory (
79+ & self ,
80+ required : usize ,
81+ _consumer : & Arc < dyn MemoryConsumer > ,
82+ ) -> usize {
6683 required
6784 }
6885
@@ -98,6 +115,15 @@ impl ConstraintExecutionMemoryPool {
98115 }
99116}
100117
118+ impl Debug for ConstraintExecutionMemoryPool {
119+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> fmt:: Result {
120+ f. debug_struct ( "ConstraintExecutionMemoryPool" )
121+ . field ( "total" , & self . pool_size )
122+ . field ( "used" , & self . memory_used ( ) )
123+ . finish ( )
124+ }
125+ }
126+
101127impl ExecutionMemoryPool for ConstraintExecutionMemoryPool {
102128 fn memory_available ( & self ) -> usize {
103129 self . pool_size - self . memory_used ( )
@@ -110,10 +136,17 @@ impl ExecutionMemoryPool for ConstraintExecutionMemoryPool {
110136
111137 fn memory_used_partition ( & self , partition_id : usize ) -> usize {
112138 let partition_usage = self . memory_usage . lock ( ) . unwrap ( ) ;
113- partition_usage[ partition_id] . unwrap_or ( 0 )
139+ match partition_usage. get ( & partition_id) {
140+ None => 0 ,
141+ Some ( v) => * v,
142+ }
114143 }
115144
116- fn acquire_memory ( & self , required : usize , consumer : & dyn MemoryConsumer ) -> usize {
145+ fn acquire_memory (
146+ & self ,
147+ required : usize ,
148+ consumer : & Arc < dyn MemoryConsumer > ,
149+ ) -> usize {
117150 assert ! ( required > 0 ) ;
118151 let partition_id = consumer. partition_id ( ) ;
119152 let mut partition_usage = self . memory_usage . lock ( ) . unwrap ( ) ;
@@ -138,7 +171,7 @@ impl ExecutionMemoryPool for ConstraintExecutionMemoryPool {
138171 Some ( max_available) => min ( required, max_available) ,
139172 } ;
140173
141- let total_used = partition_usage. values ( ) . sum ( ) ;
174+ let total_used: usize = partition_usage. values ( ) . sum ( ) ;
142175 let total_available = self . pool_size - total_used;
143176 // Only give it as much memory as is free, which might be none if it reached 1 / num_active_partition
144177 let to_grant = min ( max_grant, total_available) ;
@@ -147,8 +180,11 @@ impl ExecutionMemoryPool for ConstraintExecutionMemoryPool {
147180 // if we can't give it this much now, wait for other tasks to free up memory
148181 // (this happens if older tasks allocated lots of memory before N grew)
149182 if to_grant < required && current_mem + to_grant < min_memory_per_partition {
150- info ! ( "{} waiting for at least 1/2N of pool to be free" , consumer) ;
151- self . condvar . wait ( & mut partition_usage) ;
183+ info ! (
184+ "{:?} waiting for at least 1/2N of pool to be free" ,
185+ consumer
186+ ) ;
187+ self . condvar . wait ( partition_usage) ;
152188 } else {
153189 * partition_usage. entry ( partition_id) . or_insert ( 0 ) += to_grant;
154190 return to_grant;
@@ -169,20 +205,24 @@ impl ExecutionMemoryPool for ConstraintExecutionMemoryPool {
169205 } else {
170206 let mut partition_usage = self . memory_usage . lock ( ) . unwrap ( ) ;
171207 if granted_size > real_size {
172- partition_usage. entry ( consumer. partition_id ( ) ) -=
208+ * partition_usage. entry ( consumer. partition_id ( ) ) . or_insert ( 0 ) -=
173209 granted_size - real_size;
174210 } else {
175211 // TODO: this would have caused OOM already if size estimation ahead is much smaller than
176212 // that of actual allocation
177- partition_usage. entry ( consumer. partition_id ( ) ) +=
213+ * partition_usage. entry ( consumer. partition_id ( ) ) . or_insert ( 0 ) +=
178214 real_size - granted_size;
179215 }
180216 }
181217 }
182218
183219 fn release_memory ( & self , release_size : usize , partition_id : usize ) {
184220 let mut partition_usage = self . memory_usage . lock ( ) . unwrap ( ) ;
185- let current_mem = partition_usage[ partition_id] . unwrap_or ( 0 ) ;
221+ let current_mem = match partition_usage. get ( & partition_id) {
222+ None => 0 ,
223+ Some ( v) => * v,
224+ } ;
225+
186226 let to_free = if current_mem < release_size {
187227 warn ! (
188228 "Release called to free {} but partition only holds {} from the pool" ,
@@ -193,8 +233,9 @@ impl ExecutionMemoryPool for ConstraintExecutionMemoryPool {
193233 release_size
194234 } ;
195235 if partition_usage. contains_key ( & partition_id) {
196- partition_usage. entry ( partition_id) -= to_free;
197- if partition_usage[ partition_id] . unwrap ( ) == 0 {
236+ let entry = partition_usage. entry ( partition_id) . or_insert ( 0 ) ;
237+ * entry -= to_free;
238+ if * entry == 0 {
198239 partition_usage. remove ( & partition_id) ;
199240 }
200241 }
@@ -203,10 +244,12 @@ impl ExecutionMemoryPool for ConstraintExecutionMemoryPool {
203244
204245 fn release_all ( & self , partition_id : usize ) -> usize {
205246 let mut partition_usage = self . memory_usage . lock ( ) . unwrap ( ) ;
206- let current_mem = partition_usage[ partition_id] . unwrap_or ( 0 ) ;
207- if current_mem == 0 {
208- return 0 ;
247+ let mut current_mem = 0 ;
248+ match partition_usage. get ( & partition_id) {
249+ None => return 0 ,
250+ Some ( v) => current_mem = * v,
209251 }
252+
210253 partition_usage. remove ( & partition_id) ;
211254 self . condvar . notify_all ( ) ;
212255 return current_mem;
0 commit comments