Assessment reports>Pyth Governance>Discussion>Inefficient implementation

Inefficient get_unused_index implementation

The PositionData::get_unused_index method iterates up to 100 times looking for an available PositionData slot in the positions array. This is because closed positions are marked by taking the specified PositionData and setting that entry to None.

If, instead, this was implemented by tracking the next available index (_we'll refer to this as next_index_) used to fill a position and swapping the last position with the newly closed position, there would never be gaps in the positions. This means that get_unused_index can just return next_index after ensuring that next_index is not out of bounds (less than 100).

An example updated PositionData that would use this fast implementation for get_unused_index could look like the following:

pub struct PositionData {
    pub owner:     Pubkey,
    pub positions: [Option<Position>; MAX_POSITIONS],
    next_index: usize
}

impl PositionData {
    /// Finds first index available for a new position
    pub fn get_unused_index(&self) -> Result<usize> {
        if self.next_index < MAX_POSITIONS {
            Ok(next_index)
        } else {
            Err(error!(ErrorCode::TooManyPositions))
        }
    }
    
    pub fn add_position(&mut self, position: Position) -> Result<()> {
        let index = self.get_unused_index()?;
        self.positions[index] = Some(position);
        
        self.next_index += 1;
        
        Ok(())
    }
    
    pub fn delete_position(&mut self, position_index: usize) -> Result<()> {
        if position_index >= MAX_POSITIONS {
            return Err(error!(ErrorCode::PositionNotInUse));
        }
        
        match self.positions[position_index] {
            Some(_) => {
                self.next_index -= 1;
                self.positions[position_index] = self.positions[self.next_index];
                self.positions[self.next_index] = None;
                
                Ok(())
            },
            None => Err(error!(ErrorCode::PositionNotInUse))
        }
    }
}
Zellic © 2024Back to top ↑