-
Notifications
You must be signed in to change notification settings - Fork 396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #9204 - Overcome StdOutputRecordCount's limit of about 2.1 billion #10536
Conversation
``` [ RUN ] EnergyPlusFixture.OutputProcessor_StdoutRecordCount 2005-12-22 02:45 /home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputProcessor.unit.cc:5483: Failure Expected: (state->dataGlobal->StdOutputRecordCount) > (0), actual: -2147482095 vs 0 /home/julien/Software/Others/EnergyPlus/tst/EnergyPlus/unit/OutputProcessor.unit.cc:5484: Failure Expected: (state->dataGlobal->StdMeterRecordCount) > (0), actual: -2147483648 vs 0 ```
…4_t) This increases the limit from 2,147,483,648 to 9,223,372,036,854,775,808 records
Int64 StdOutputRecordCount = 0; // Count of Standard output records | ||
Int64 StdMeterRecordCount = 0; // Count of Meter output records |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change StdOutputRecordCount & StdMeterRecordCount to Int64 (std::int64_t)
This increases the limit from 2,147,483,648 to 9,223,372,036,854,775,808 records
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmm. OK, I believe you. I guess that should be big enough 😆
@@ -57,7 +57,7 @@ fs::path configured_source_directory() | |||
|
|||
fs::path configured_build_directory() | |||
{ | |||
return ("${CMAKE_BUILD_DIR}"); | |||
return ("${CMAKE_BINARY_DIR}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated but was incorrect. I tried to use that to use an actual eso & mtr file instead of the open_as_stringstream to see if the test could work fast enough, but no.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow. Good catch.
// Demonstrate that it's not unreasonable to reach the INT_MAX limit at all | ||
constexpr int numOfTimeStepInHour = 60; | ||
constexpr int hoursInYear = 8760; | ||
constexpr int numOutputVariables = 4200; | ||
constexpr size_t totalRecords = | ||
static_cast<size_t>(numOfTimeStepInHour) * static_cast<size_t>(hoursInYear) * static_cast<size_t>(numOutputVariables); | ||
|
||
constexpr auto INT_MAX_AS_SIZE_T = static_cast<size_t>(INT_MAX); | ||
EXPECT_GT(totalRecords, INT_MAX_AS_SIZE_T); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not unreasonable to hit the INT_MAX limit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK OK I said I believed you.
// NOTE: the test takes way to long to run if do call UpdateMeterReporting and UpdateDataandReport | ||
// So I'm going to just scan for a timestamp were we're about to overflow, and fake it | ||
size_t records_written = 0; | ||
bool found_about_to_overflow = false; | ||
for (state->dataEnvrn->Month = 1; state->dataEnvrn->Month <= 12; ++state->dataEnvrn->Month) { | ||
state->dataEnvrn->EndMonthFlag = false; | ||
for (state->dataEnvrn->DayOfMonth = 1; state->dataEnvrn->DayOfMonth <= state->dataWeather->EndDayOfMonth(state->dataEnvrn->Month); | ||
++state->dataEnvrn->DayOfMonth) { | ||
|
||
++state->dataGlobal->DayOfSim; | ||
state->dataGlobal->DayOfSimChr = fmt::to_string(state->dataGlobal->DayOfSim); | ||
|
||
++state->dataEnvrn->DayOfWeek; | ||
if (state->dataEnvrn->DayOfWeek > 7) { | ||
state->dataEnvrn->DayOfWeek = 1; | ||
} | ||
|
||
state->dataGlobal->EndDayFlag = false; | ||
for (state->dataGlobal->HourOfDay = 1; state->dataGlobal->HourOfDay <= 24; ++state->dataGlobal->HourOfDay) { | ||
for (state->dataGlobal->TimeStep = 1; state->dataGlobal->TimeStep <= state->dataGlobal->NumOfTimeStepInHour; | ||
++state->dataGlobal->TimeStep) { | ||
if (state->dataGlobal->TimeStep == state->dataGlobal->NumOfTimeStepInHour) { | ||
state->dataGlobal->EndHourFlag = true; | ||
if (state->dataGlobal->HourOfDay == 24) { | ||
state->dataGlobal->EndDayFlag = true; | ||
if ((!state->dataGlobal->WarmupFlag) && (state->dataGlobal->DayOfSim == state->dataGlobal->NumOfDayInEnvrn)) { | ||
state->dataGlobal->EndEnvrnFlag = true; | ||
} | ||
} | ||
} | ||
|
||
if (state->dataEnvrn->DayOfMonth == state->dataWeather->EndDayOfMonth(state->dataEnvrn->Month)) { | ||
state->dataEnvrn->EndMonthFlag = true; | ||
} | ||
records_written += numOutputVariables; | ||
if (records_written > (INT_MAX_AS_SIZE_T - numOutputVariables)) { | ||
EXPECT_EQ("2005-12-22 02:45", | ||
fmt::format("{:04d}-{:02d}-{:02d} {:02d}:{:02d}", | ||
state->dataGlobal->CalendarYear, | ||
state->dataEnvrn->Month, | ||
state->dataEnvrn->DayOfMonth, | ||
state->dataGlobal->HourOfDay, | ||
state->dataGlobal->TimeStep)); | ||
UpdateMeterReporting(*state); | ||
UpdateDataandReport(*state, TimeStepType::Zone); | ||
found_about_to_overflow = true; | ||
break; | ||
} | ||
} | ||
if (found_about_to_overflow) { | ||
break; | ||
} | ||
} | ||
if (found_about_to_overflow) { | ||
break; | ||
} | ||
} | ||
if (found_about_to_overflow) { | ||
break; | ||
} | ||
} | ||
ASSERT_TRUE(found_about_to_overflow); | ||
EXPECT_EQ(numOutputVariables + 1, state->dataGlobal->StdOutputRecordCount); | ||
EXPECT_EQ(1, state->dataGlobal->StdMeterRecordCount); | ||
EXPECT_TRUE(has_eso_output(true)); | ||
state->dataGlobal->StdOutputRecordCount = records_written; | ||
state->dataGlobal->StdMeterRecordCount = INT_MAX; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fake having written the record for all timesteps until it overflows. if I don't fake it, it's unbearably slow
++state->dataGlobal->TimeStep; | ||
|
||
UpdateMeterReporting(*state); | ||
UpdateDataandReport(*state, TimeStepType::Zone); | ||
EXPECT_GT(state->dataGlobal->StdOutputRecordCount, 0); | ||
EXPECT_GT(state->dataGlobal->StdMeterRecordCount, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get it to overflow over INT_MAX
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great. And testing locally for kicks.
@@ -57,7 +57,7 @@ fs::path configured_source_directory() | |||
|
|||
fs::path configured_build_directory() | |||
{ | |||
return ("${CMAKE_BUILD_DIR}"); | |||
return ("${CMAKE_BINARY_DIR}"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow. Good catch.
Int64 StdOutputRecordCount = 0; // Count of Standard output records | ||
Int64 StdMeterRecordCount = 0; // Count of Meter output records |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmmm. OK, I believe you. I guess that should be big enough 😆
// Demonstrate that it's not unreasonable to reach the INT_MAX limit at all | ||
constexpr int numOfTimeStepInHour = 60; | ||
constexpr int hoursInYear = 8760; | ||
constexpr int numOutputVariables = 4200; | ||
constexpr size_t totalRecords = | ||
static_cast<size_t>(numOfTimeStepInHour) * static_cast<size_t>(hoursInYear) * static_cast<size_t>(numOutputVariables); | ||
|
||
constexpr auto INT_MAX_AS_SIZE_T = static_cast<size_t>(INT_MAX); | ||
EXPECT_GT(totalRecords, INT_MAX_AS_SIZE_T); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK OK I said I believed you.
++state->dataGlobal->TimeStep; | ||
|
||
UpdateMeterReporting(*state); | ||
UpdateDataandReport(*state, TimeStepType::Zone); | ||
EXPECT_GT(state->dataGlobal->StdOutputRecordCount, 0); | ||
EXPECT_GT(state->dataGlobal->StdMeterRecordCount, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
All happy here. Let's merge. Thanks @jmarrec |
Pull request overview
It's pretty much all unit testing... the fix was trivial, the test was clearly not.
Pull Request Author
Add to this list or remove from it as applicable. This is a simple templated set of guidelines.
Reviewer
This will not be exhaustively relevant to every PR.