1818//! [`MemoryPool`] for memory management during query execution, [`proxy`] for
1919//! help with allocation accounting.
2020
21- use datafusion_common:: { Result , internal_err } ;
21+ use datafusion_common:: { Result , internal_datafusion_err } ;
2222use std:: hash:: { Hash , Hasher } ;
2323use std:: { cmp:: Ordering , sync:: Arc , sync:: atomic} ;
2424
@@ -322,7 +322,7 @@ impl MemoryConsumer {
322322 pool : Arc :: clone ( pool) ,
323323 consumer : self ,
324324 } ) ,
325- size : 0 ,
325+ size : atomic :: AtomicUsize :: new ( 0 ) ,
326326 }
327327 }
328328}
@@ -351,13 +351,13 @@ impl Drop for SharedRegistration {
351351#[ derive( Debug ) ]
352352pub struct MemoryReservation {
353353 registration : Arc < SharedRegistration > ,
354- size : usize ,
354+ size : atomic :: AtomicUsize ,
355355}
356356
357357impl MemoryReservation {
358358 /// Returns the size of this reservation in bytes
359359 pub fn size ( & self ) -> usize {
360- self . size
360+ self . size . load ( atomic :: Ordering :: Relaxed )
361361 }
362362
363363 /// Returns [MemoryConsumer] for this [MemoryReservation]
@@ -367,8 +367,8 @@ impl MemoryReservation {
367367
368368 /// Frees all bytes from this reservation back to the underlying
369369 /// pool, returning the number of bytes freed.
370- pub fn free ( & mut self ) -> usize {
371- let size = self . size ;
370+ pub fn free ( & self ) -> usize {
371+ let size = self . size . load ( atomic :: Ordering :: Relaxed ) ;
372372 if size != 0 {
373373 self . shrink ( size)
374374 }
@@ -380,60 +380,62 @@ impl MemoryReservation {
380380 /// # Panics
381381 ///
382382 /// Panics if `capacity` exceeds [`Self::size`]
383- pub fn shrink ( & mut self , capacity : usize ) {
384- let new_size = self . size . checked_sub ( capacity) . unwrap ( ) ;
383+ pub fn shrink ( & self , capacity : usize ) {
384+ self . size . fetch_sub ( capacity, atomic :: Ordering :: Relaxed ) ;
385385 self . registration . pool . shrink ( self , capacity) ;
386- self . size = new_size
387386 }
388387
389388 /// Tries to free `capacity` bytes from this reservation
390389 /// if `capacity` does not exceed [`Self::size`]
391390 /// Returns new reservation size
392391 /// or error if shrinking capacity is more than allocated size
393- pub fn try_shrink ( & mut self , capacity : usize ) -> Result < usize > {
394- if let Some ( new_size) = self . size . checked_sub ( capacity) {
395- self . registration . pool . shrink ( self , capacity) ;
396- self . size = new_size;
397- Ok ( new_size)
398- } else {
399- internal_err ! (
400- "Cannot free the capacity {capacity} out of allocated size {}" ,
401- self . size
392+ pub fn try_shrink ( & self , capacity : usize ) -> Result < usize > {
393+ let updated = self . size . fetch_update (
394+ atomic:: Ordering :: Relaxed ,
395+ atomic:: Ordering :: Relaxed ,
396+ |prev| prev. checked_sub ( capacity) ,
397+ ) ;
398+ updated. map_err ( |_| {
399+ let prev = self . size . load ( atomic:: Ordering :: Relaxed ) ;
400+ internal_datafusion_err ! (
401+ "Cannot free the capacity {capacity} out of allocated size {prev}"
402402 )
403- }
403+ } )
404404 }
405405
406406 /// Sets the size of this reservation to `capacity`
407- pub fn resize ( & mut self , capacity : usize ) {
408- match capacity. cmp ( & self . size ) {
409- Ordering :: Greater => self . grow ( capacity - self . size ) ,
410- Ordering :: Less => self . shrink ( self . size - capacity) ,
407+ pub fn resize ( & self , capacity : usize ) {
408+ let size = self . size . load ( atomic:: Ordering :: Relaxed ) ;
409+ match capacity. cmp ( & size) {
410+ Ordering :: Greater => self . grow ( capacity - size) ,
411+ Ordering :: Less => self . shrink ( size - capacity) ,
411412 _ => { }
412413 }
413414 }
414415
415416 /// Try to set the size of this reservation to `capacity`
416- pub fn try_resize ( & mut self , capacity : usize ) -> Result < ( ) > {
417- match capacity. cmp ( & self . size ) {
418- Ordering :: Greater => self . try_grow ( capacity - self . size ) ?,
419- Ordering :: Less => self . shrink ( self . size - capacity) ,
417+ pub fn try_resize ( & self , capacity : usize ) -> Result < ( ) > {
418+ let size = self . size . load ( atomic:: Ordering :: Relaxed ) ;
419+ match capacity. cmp ( & size) {
420+ Ordering :: Greater => self . try_grow ( capacity - size) ?,
421+ Ordering :: Less => self . shrink ( size - capacity) ,
420422 _ => { }
421423 } ;
422424 Ok ( ( ) )
423425 }
424426
425427 /// Increase the size of this reservation by `capacity` bytes
426- pub fn grow ( & mut self , capacity : usize ) {
428+ pub fn grow ( & self , capacity : usize ) {
427429 self . registration . pool . grow ( self , capacity) ;
428- self . size += capacity;
430+ self . size . fetch_add ( capacity, atomic :: Ordering :: Relaxed ) ;
429431 }
430432
431433 /// Try to increase the size of this reservation by `capacity`
432434 /// bytes, returning error if there is insufficient capacity left
433435 /// in the pool.
434- pub fn try_grow ( & mut self , capacity : usize ) -> Result < ( ) > {
436+ pub fn try_grow ( & self , capacity : usize ) -> Result < ( ) > {
435437 self . registration . pool . try_grow ( self , capacity) ?;
436- self . size += capacity;
438+ self . size . fetch_add ( capacity, atomic :: Ordering :: Relaxed ) ;
437439 Ok ( ( ) )
438440 }
439441
@@ -447,26 +449,32 @@ impl MemoryReservation {
447449 /// # Panics
448450 ///
449451 /// Panics if `capacity` exceeds [`Self::size`]
450- pub fn split ( & mut self , capacity : usize ) -> MemoryReservation {
451- self . size = self . size . checked_sub ( capacity) . unwrap ( ) ;
452+ pub fn split ( & self , capacity : usize ) -> MemoryReservation {
453+ self . size
454+ . fetch_update (
455+ atomic:: Ordering :: Relaxed ,
456+ atomic:: Ordering :: Relaxed ,
457+ |prev| prev. checked_sub ( capacity) ,
458+ )
459+ . unwrap ( ) ;
452460 Self {
453- size : capacity,
461+ size : atomic :: AtomicUsize :: new ( capacity) ,
454462 registration : Arc :: clone ( & self . registration ) ,
455463 }
456464 }
457465
458466 /// Returns a new empty [`MemoryReservation`] with the same [`MemoryConsumer`]
459467 pub fn new_empty ( & self ) -> Self {
460468 Self {
461- size : 0 ,
469+ size : atomic :: AtomicUsize :: new ( 0 ) ,
462470 registration : Arc :: clone ( & self . registration ) ,
463471 }
464472 }
465473
466474 /// Splits off all the bytes from this [`MemoryReservation`] into
467475 /// a new [`MemoryReservation`] with the same [`MemoryConsumer`]
468476 pub fn take ( & mut self ) -> MemoryReservation {
469- self . split ( self . size )
477+ self . split ( self . size . load ( atomic :: Ordering :: Relaxed ) )
470478 }
471479}
472480
@@ -492,7 +500,7 @@ mod tests {
492500 #[ test]
493501 fn test_memory_pool_underflow ( ) {
494502 let pool = Arc :: new ( GreedyMemoryPool :: new ( 50 ) ) as _ ;
495- let mut a1 = MemoryConsumer :: new ( "a1" ) . register ( & pool) ;
503+ let a1 = MemoryConsumer :: new ( "a1" ) . register ( & pool) ;
496504 assert_eq ! ( pool. reserved( ) , 0 ) ;
497505
498506 a1. grow ( 100 ) ;
@@ -507,7 +515,7 @@ mod tests {
507515 a1. try_grow ( 30 ) . unwrap ( ) ;
508516 assert_eq ! ( pool. reserved( ) , 30 ) ;
509517
510- let mut a2 = MemoryConsumer :: new ( "a2" ) . register ( & pool) ;
518+ let a2 = MemoryConsumer :: new ( "a2" ) . register ( & pool) ;
511519 a2. try_grow ( 25 ) . unwrap_err ( ) ;
512520 assert_eq ! ( pool. reserved( ) , 30 ) ;
513521
@@ -521,7 +529,7 @@ mod tests {
521529 #[ test]
522530 fn test_split ( ) {
523531 let pool = Arc :: new ( GreedyMemoryPool :: new ( 50 ) ) as _ ;
524- let mut r1 = MemoryConsumer :: new ( "r1" ) . register ( & pool) ;
532+ let r1 = MemoryConsumer :: new ( "r1" ) . register ( & pool) ;
525533
526534 r1. try_grow ( 20 ) . unwrap ( ) ;
527535 assert_eq ! ( r1. size( ) , 20 ) ;
@@ -542,10 +550,10 @@ mod tests {
542550 #[ test]
543551 fn test_new_empty ( ) {
544552 let pool = Arc :: new ( GreedyMemoryPool :: new ( 50 ) ) as _ ;
545- let mut r1 = MemoryConsumer :: new ( "r1" ) . register ( & pool) ;
553+ let r1 = MemoryConsumer :: new ( "r1" ) . register ( & pool) ;
546554
547555 r1. try_grow ( 20 ) . unwrap ( ) ;
548- let mut r2 = r1. new_empty ( ) ;
556+ let r2 = r1. new_empty ( ) ;
549557 r2. try_grow ( 5 ) . unwrap ( ) ;
550558
551559 assert_eq ! ( r1. size( ) , 20 ) ;
@@ -559,7 +567,7 @@ mod tests {
559567 let mut r1 = MemoryConsumer :: new ( "r1" ) . register ( & pool) ;
560568
561569 r1. try_grow ( 20 ) . unwrap ( ) ;
562- let mut r2 = r1. take ( ) ;
570+ let r2 = r1. take ( ) ;
563571 r2. try_grow ( 5 ) . unwrap ( ) ;
564572
565573 assert_eq ! ( r1. size( ) , 0 ) ;
0 commit comments