Je ne comprends pas la gestion de la mémoire dans l'API C++ Arrow. J'utilise Arrow 1.0.0 et je lis un fichier CSV. Après quelques exécutions de ReadArrowTableFromCSV, ma mémoire est pleine de données allouées. Est-ce que j'ai raté quelque chose ? Comment puis-je libérer cette mémoire ? Je ne vois aucune méthode dans le pool de mémoire pour effacer toute la mémoire allouée. Liste de codes ci-dessous.

void LoadCSVData::ReadArrowTableFromCSV( const std::string & filePath )
{
    auto tableReader = CreateTableReader( filePath );
    ReadArrowTableUsingReader( *tableReader );
}

std::shared_ptr<arrow::csv::TableReader> LoadCSVData::CreateTableReader( const std::string & filePath )
{
    arrow::MemoryPool* pool = arrow::default_memory_pool();
    auto tableReader = arrow::csv::TableReader::Make( pool, OpenCSVFile( filePath ),
                                                      *PrepareReadOptions(), *PrepareParseOptions(), *PrepareConvertOptions() );
    if ( !tableReader.ok() )
    {
        throw BadParametersException( std::string( "CSV file reader error: " ) + tableReader.status().ToString() );
    }
    return *tableReader;
}

void LoadCSVData::ReadArrowTableUsingReader( arrow::csv::TableReader & reader )
{
    auto table = reader.Read();
    if ( !table.ok() )
    {
        throw BadParametersException( std::string( "CSV file reader error: " ) + table.status().ToString() );
    }
    this->mArrowTable = *table;
}

std::unique_ptr<arrow::csv::ParseOptions> LoadCSVData::PrepareParseOptions()
{
    auto parseOptions = std::make_unique<arrow::csv::ParseOptions>( arrow::csv::ParseOptions::Defaults() );
    parseOptions->delimiter = mDelimiter;
    return parseOptions;
}

std::unique_ptr<arrow::csv::ReadOptions> LoadCSVData::PrepareReadOptions()
{
    auto readOptions = std::make_unique<arrow::csv::ReadOptions>( arrow::csv::ReadOptions::Defaults() );
    readOptions->skip_rows = mNumberOfHeaderRows;
    readOptions->block_size = 1 << 27;  // 128 MB
    readOptions->column_names.reserve( mTable->GetNumberOfColumns() );

    for ( auto & colName : mTable->GetColumnsOrder() )
    {
        readOptions->column_names.emplace_back( colName );
    }

    return readOptions;
}

std::unique_ptr<arrow::csv::ConvertOptions> LoadCSVData::PrepareConvertOptions() const
{
    auto convertOptions = std::make_unique<arrow::csv::ConvertOptions>( arrow::csv::ConvertOptions::Defaults() );
    for ( auto & col : mTable->GetColumsInfo() )
    {
        convertOptions->column_types[col.second.GetName()] = MyTypeToArrowDataType( col.second.GetType() );
    }
    convertOptions->strings_can_be_null = true;

    return convertOptions;
}

std::shared_ptr<arrow::io::ReadableFile> LoadCSVData::OpenCSVFile( const std::string & filePath )
{
    MTR_SCOPE_FUNC();
    auto inputFileResult = arrow::io::ReadableFile::Open( filePath );
    if ( !inputFileResult.ok() )
    {
        throw BadParametersException( std::string( "CSV file reader error: " ) + inputFileResult.status().ToString() );
    }
    return *inputFileResult;
}
1
Maciej S 8 nov. 2020 à 23:14

1 réponse

Meilleure réponse

Maciej, la méthode TableReader::Read devrait retourner shared_ptr<arrow::Table>. Le arrow::Table lui-même a un certain nombre de pointeurs partagés vers des structures qui contiennent éventuellement les données. Pour libérer les données, vous devrez vous assurer que le arrow::Table et toute copie de celui-ci sont détruits. Cela devrait se produire dès que shared_ptr sera hors de portée. Cependant, il semble que vous stockez la table dans une variable membre ici (ce qui est normal, vous souhaiterez probablement utiliser les données après les avoir lues):

this->mArrowTable = *table;

Vous avez donc maintenant une deuxième copie de l'instance arrow::Table. Vous pouvez réaffecter this->mArrowTable à une nouvelle table vide ou vous pouvez détruire ce que this est. Bien sûr, si vous faites d'autres copies du tableau, vous devrez vous assurer qu'elles sortent également du champ d'application.

1
Pace 13 nov. 2020 à 18:07