Skip to content

Commit

Permalink
Pickle API: Cache unpickled Series to avoid repeated file access (#1654)
Browse files Browse the repository at this point in the history
* Cache the Series per thread

* Fixes for Windows
  • Loading branch information
franzpoeschel authored Oct 30, 2024
1 parent de67eff commit 2a36ef8
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
38 changes: 35 additions & 3 deletions include/openPMD/binding/python/Pickle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include "openPMD/IO/Access.hpp"
#include "openPMD/Series.hpp"
#include "openPMD/auxiliary/StringManip.hpp"
#include "openPMD/backend/Attributable.hpp"

#include "Common.hpp"
Expand Down Expand Up @@ -67,9 +68,40 @@ add_pickle(pybind11::class_<T_Args...> &cl, T_SeriesAccessor &&seriesAccessor)
std::vector<std::string> const group =
t[1].cast<std::vector<std::string> >();

openPMD::Series series(
filename, Access::READ_ONLY, "defer_iteration_parsing = true");
return seriesAccessor(std::move(series), group);
/*
* Cache the Series per thread.
*/
thread_local std::optional<openPMD::Series> series;
bool re_initialize = [&]() {
try
{
return !series.has_value() || !series->operator bool() ||
auxiliary::replace_all(
series->myPath().filePath(), "\\", "/") !=
auxiliary::replace_all(filename, "\\", "/");
}
/*
* Better safe than sorry, if anything goes wrong because the
* Series is in a weird state, just reinitialize it.
*/
catch (...)
{
return true;
}
}();
if (re_initialize)
{
/*
* Do NOT close the old Series, it might still be active in
* terms of handed-out handles.
*/
series = std::make_optional<Series>(
filename,
Access::READ_ONLY,
"defer_iteration_parsing = true");
}

return seriesAccessor(*series, group);
}));
}
} // namespace openPMD
9 changes: 9 additions & 0 deletions test/SerialIOTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,9 @@ void write_and_read_many_iterations(

{
Series write(filename, Access::CREATE);
REQUIRE(
auxiliary::replace_all(write.myPath().filePath(), "\\", "/") ==
auxiliary::replace_all(filename, "\\", "/"));
for (unsigned int i = 0; i < nIterations; ++i)
{
// std::cout << "Putting iteration " << i << std::endl;
Expand Down Expand Up @@ -1851,6 +1854,12 @@ inline void fileBased_write_test(const std::string &backend)
"../samples/subdir/serial_fileBased_write%03T." + backend,
Access::CREATE,
jsonCfg);
REQUIRE(
auxiliary::replace_all(o.myPath().filePath(), "\\", "/") ==
auxiliary::replace_all(
"../samples/subdir/serial_fileBased_write%03T." + backend,
"\\",
"/"));

ParticleSpecies &e_1 = o.iterations[1].particles["e"];

Expand Down

0 comments on commit 2a36ef8

Please sign in to comment.