Skip to content

Commit

Permalink
Switch static std::array to std::vector for interval based MinaCalc c…
Browse files Browse the repository at this point in the history
…ontainers

Due to a change in MSVC 16.7 it appears that static arrays of a large size take a simply unacceptable amount of RAM/heap to compile. This kills GHA as well as almost our local machines. This is a change that "fixes" the issue by removing the very large static arrays.

Although this behavior may be due to a real MSVC bug, this change is useful on its own to allow a somewhat greater range of files. But still, the difference between 40k intervals and 100k intervals for a max size is basically nothing in the grand scheme of files available. Most files fall within 500-1000 intervals (4-8 minutes).
#890
  • Loading branch information
poco0317 committed Aug 28, 2020
1 parent 0e9dea8 commit 8c4abf5
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 21 deletions.
8 changes: 4 additions & 4 deletions src/Etterna/MinaCalc/MinaCalc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,11 @@ StamAdjust(const float x,
const auto super_stam_ceil = 1.11F;

// use this to calculate the mod growth
const std::array<float, max_intervals>* base_diff =
const std::vector<float>* base_diff =
&(calc.base_diff_for_stam_mod.at(hi).at(ss));
// but apply the mod growth to these values
// they might be the same, or not
const std::array<float, max_intervals>* diff =
const std::vector<float>* diff =
&(calc.base_adj_diff.at(hi).at(ss));

// i don't like the copypasta either but the boolchecks where
Expand Down Expand Up @@ -407,7 +407,7 @@ CalcInternal(float& gotpoints,
}

// final difficulty values to use
const std::array<float, max_intervals>* v =
const std::vector<float>* v =
&(stam ? calc.stam_adj_diff : calc.base_adj_diff.at(hi).at(ss));
auto powindromemordniwop = 1.7F;
if (ss == Skill_Chordjack) {
Expand Down Expand Up @@ -943,7 +943,7 @@ MinaSDCalcDebug(
}
}

int mina_calc_version = 439;
int mina_calc_version = 440;
auto
GetCalcVersion() -> int
{
Expand Down
63 changes: 51 additions & 12 deletions src/Etterna/MinaCalc/MinaCalc.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ using MinaSD = std::vector<std::vector<float>>;

class Calc;

// should be able to handle 1hr 54min easily
static const int max_intervals = 40000;
// intervals are half seconds
// this number is a default which should work for most files
// the calc should internally grow the vector if a larger number is needed
static const int default_interval_count = 1000;

// this should allow for anything except for things like 24 hours of stream
// 24 hours of 100 bpm stream takes up around 130k intervals
// this cap will prevent extremely unnecessary huge allocations for end users
static const int max_intervals = 100000;

/* intervals are _half_ second, no point in wasting time or cpu cycles on 100
* nps joke files. even at most generous, 100 nps spread across all fingers,
Expand Down Expand Up @@ -87,23 +94,25 @@ class Calc
static inline void InitAdjDiff(Calc& calc, const int& hi);

public:
// the most basic derviations from the most basic notedata
std::array<std::array<RowInfo, max_rows_for_single_interval>, max_intervals>
Calc() { resize_interval_dependent_vectors(default_interval_count); }

// the most basic derivations from the most basic notedata
std::vector<std::array<RowInfo, max_rows_for_single_interval>>
adj_ni;

// size of each interval in rows
std::array<int, max_intervals> itv_size{};
std::vector<int> itv_size{};

// Point allotment for each interval
std::array<std::array<int, max_intervals>, num_hands> itv_points{};
std::array<std::vector<int>, num_hands> itv_points{};

// holds pattern mods
std::array<std::array<std::array<float, max_intervals>, NUM_CalcPatternMod>,
std::array<std::array<std::vector<float>, NUM_CalcPatternMod>,
num_hands>
doot{};

// Calculated difficulty for each interval
std::array<std::array<std::array<float, max_intervals>, NUM_CalcDiffValue>,
std::array<std::array<std::vector<float>, NUM_CalcDiffValue>,
num_hands>
soap{};

Expand All @@ -124,12 +133,12 @@ class Calc
* any way, and no estimation is made on how much this actually messes with
* stuff (could be minor, could be major, could be minor for most files and
* major for a select few) */
std::array<std::array<std::array<float, max_intervals>, NUM_Skillset>,
std::array<std::array<std::vector<float>, NUM_Skillset>,
num_hands>
base_adj_diff{};

// input that the stamina model uses to apply to the base diff
std::array<std::array<std::array<float, max_intervals>, NUM_Skillset>,
std::array<std::array<std::vector<float>, NUM_Skillset>,
num_hands>
base_diff_for_stam_mod{};

Expand All @@ -138,13 +147,13 @@ class Calc
* value changes, again based on the above, technically we could use the
* skill_stamina element of the arrays to store this and save an allocation
* but that might just be too confusing idk */
std::array<float, max_intervals> stam_adj_diff{};
std::vector<float> stam_adj_diff{};

// a vector of {row_time, diff} for each hand
std::array<std::vector<std::pair<float, float>>, num_hands> jack_diff{};

// number of jacks by hand for intervals
// std::array<std::array<int, max_intervals>, num_hands>
// std::array<std::vector<int>, num_hands>
// itv_jack_diff_size{};

std::array<std::vector<float>, num_hands> jack_loss{};
Expand All @@ -166,6 +175,36 @@ class Calc
* pulled straight from the calc */
std::array<std::vector<std::vector<std::vector<float>>>, num_hands>
debugValues;

// grow every interval-dependent vector we use
// the size could be reduced but there isn't a big need for it
// this does nothing if amt < the size of the vectors
void resize_interval_dependent_vectors(size_t amt)
{
// there isn't a real need to make our vectors smaller
if (amt < adj_ni.size())
return;

// grow each vector
// resize is used to construct defaults, the space should be used immediately
adj_ni.resize(amt);
itv_size.resize(amt);
for (auto& v : itv_points)
v.resize(amt);
for (auto& a : doot)
for (auto& v : a)
v.resize(amt);
for (auto& a : soap)
for (auto& v : a)
v.resize(amt);
for (auto& a : base_adj_diff)
for (auto& v : a)
v.resize(amt);
for (auto& a : base_diff_for_stam_mod)
for (auto& v : a)
v.resize(amt);
stam_adj_diff.resize(amt);
}
};

MINACALC_API auto
Expand Down
14 changes: 9 additions & 5 deletions src/Etterna/MinaCalc/UlbuAcolytes.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ static const std::array<unsigned, num_hands> hand_col_ids = { 3, 12 };
constexpr float interval_span = 0.5F;

inline void
Smooth(std::array<float, max_intervals>& input,
Smooth(std::vector<float>& input,
const float neutral,
const int end_interval)
{
Expand All @@ -34,7 +34,7 @@ Smooth(std::array<float, max_intervals>& input,
}

inline void
MSSmooth(std::array<float, max_intervals>& input,
MSSmooth(std::vector<float>& input,
const float neutral,
const int end_interval)
{
Expand Down Expand Up @@ -125,9 +125,13 @@ fast_walk_and_check_for_skip(const std::vector<NoteInfo>& ni,
* the end */
calc.numitv = time_to_itv_idx(ni.back().rowTime / rate) + 1;

// are there more intervals than our alloted max
if (calc.numitv >= max_intervals) {
return true;
// are there more intervals than our emplaced max
if (calc.numitv >= calc.itv_size.size()) {
// hard cap for memory considerations
if (calc.numitv >= max_intervals)
return true;
// accesses can happen way at the end so give it some breathing room
calc.resize_interval_dependent_vectors(calc.numitv + 2);
}

// for various reasons we actually have to do this, scan the file and make
Expand Down
1 change: 1 addition & 0 deletions src/Etterna/Singletons/LuaManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "arch/Dialog/Dialog.h"
#include "ver.h"

#include <algorithm>
#include <array>
#include <cassert>
#include <csetjmp>
Expand Down

0 comments on commit 8c4abf5

Please sign in to comment.