Skip to content

Commit 2a36ef8

Browse files
Pickle API: Cache unpickled Series to avoid repeated file access (#1654)
* Cache the Series per thread * Fixes for Windows
1 parent de67eff commit 2a36ef8

2 files changed

Lines changed: 44 additions & 3 deletions

File tree

include/openPMD/binding/python/Pickle.hpp

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "openPMD/IO/Access.hpp"
2424
#include "openPMD/Series.hpp"
25+
#include "openPMD/auxiliary/StringManip.hpp"
2526
#include "openPMD/backend/Attributable.hpp"
2627

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

70-
openPMD::Series series(
71-
filename, Access::READ_ONLY, "defer_iteration_parsing = true");
72-
return seriesAccessor(std::move(series), group);
71+
/*
72+
* Cache the Series per thread.
73+
*/
74+
thread_local std::optional<openPMD::Series> series;
75+
bool re_initialize = [&]() {
76+
try
77+
{
78+
return !series.has_value() || !series->operator bool() ||
79+
auxiliary::replace_all(
80+
series->myPath().filePath(), "\\", "/") !=
81+
auxiliary::replace_all(filename, "\\", "/");
82+
}
83+
/*
84+
* Better safe than sorry, if anything goes wrong because the
85+
* Series is in a weird state, just reinitialize it.
86+
*/
87+
catch (...)
88+
{
89+
return true;
90+
}
91+
}();
92+
if (re_initialize)
93+
{
94+
/*
95+
* Do NOT close the old Series, it might still be active in
96+
* terms of handed-out handles.
97+
*/
98+
series = std::make_optional<Series>(
99+
filename,
100+
Access::READ_ONLY,
101+
"defer_iteration_parsing = true");
102+
}
103+
104+
return seriesAccessor(*series, group);
73105
}));
74106
}
75107
} // namespace openPMD

test/SerialIOTest.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ void write_and_read_many_iterations(
177177

178178
{
179179
Series write(filename, Access::CREATE);
180+
REQUIRE(
181+
auxiliary::replace_all(write.myPath().filePath(), "\\", "/") ==
182+
auxiliary::replace_all(filename, "\\", "/"));
180183
for (unsigned int i = 0; i < nIterations; ++i)
181184
{
182185
// std::cout << "Putting iteration " << i << std::endl;
@@ -1851,6 +1854,12 @@ inline void fileBased_write_test(const std::string &backend)
18511854
"../samples/subdir/serial_fileBased_write%03T." + backend,
18521855
Access::CREATE,
18531856
jsonCfg);
1857+
REQUIRE(
1858+
auxiliary::replace_all(o.myPath().filePath(), "\\", "/") ==
1859+
auxiliary::replace_all(
1860+
"../samples/subdir/serial_fileBased_write%03T." + backend,
1861+
"\\",
1862+
"/"));
18541863

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

0 commit comments

Comments
 (0)