Too long to save
Moderator: OpenTTD Developers
Too long to save
When any script terminates on saving with the error message that it took 'too long' to save, what does this mean specifically?
How long is too long?
Note: you can reproduce this error by saving a large amount of data. (Mine failed to save about 40,000 integers, or about 160 kB).
How long is too long?
Note: you can reproduce this error by saving a large amount of data. (Mine failed to save about 40,000 integers, or about 160 kB).
Re: Too long to save
It's not about the amount of data you store, but the amount of ticks used in the Save() function. I think the limit is 100k opcodes, but I'm not entirely sure on that. This limit is in place to make sure scripts can't "hang" in the save function. Try to either save less data or make sure the data you want to save is always prepared to your Save() function can be fast.
Re: Too long to save
I've been experimenting a lot, but how to do it even faster than this?
Or maybe a way to increase the limit? Does making parts of the data members of classes static (where this can be done) help?
Code: Select all
function Scriptname::Save(){return{this};}
Re: Too long to save
Even something like
(Where data is a table, already filled with the data/classes to be saved).
Edit: Apparently, I've found the cause of the problem after about a month...
is different from
I'm unsure what the second statement does, but apparently it always causes a hang.
won't work.Code: Select all
function ScriptName::Save(return data;)
(Where data is a table, already filled with the data/classes to be saved).
Edit: Apparently, I've found the cause of the problem after about a month...
Code: Select all
return {
x = 0
};
Code: Select all
return
{
x = 0
};
Re: Too long to save
My guess is that the second version the line "return" is seen a complete statement, the semicolon at the end is optional in squirrel. This means that the function returns nothing, or "null". What the first case is supposed to do I'm unsure, is that even valid?
Re: Too long to save
The first returns a table. Syntax for table (size n) is:
and you can add stuff with
where entryname does not exist in the table yet.
Anywho, I've solved the problem by doing a very cool little trick. I made various variables static, and copied from my classes the bare minimum needed to save. It meant random effects would
be regenned on load and I had to cut a feature here and there, but in theory, it works.
Notice the typeof checks, some elements in the array can be 'null'.
EDIT: This code doesn't work because of the single float element. This means I need to somehow save this data differently. How is the question.
entry_i and var_i can be any variable name of any type.my_table = {
entry_1 = var_1
...
entry_n = var_n}
and you can add stuff with
Code: Select all
my_table.entryname <- variable
Anywho, I've solved the problem by doing a very cool little trick. I made various variables static, and copied from my classes the bare minimum needed to save. It meant random effects would
be regenned on load and I had to cut a feature here and there, but in theory, it works.
Code: Select all
function CityBuilder::Save()
{
Log.Info("Saving data", Log.LVL_INFO);
data = { sv_mode = mode,
sv_registered_companies = registered_companies,
sv_go = go,
sv_last_date = last_date,
sv_month =month,
sv_game_length = game_length,
sv_start_year = start_year,
sv_metro_town_id = metro_town_id,
sv_companies = array(companies.len(), []),
// these four are heavy!
sv_town_access = town_access,
sv_city_access = city_access,
sv_towns = array(towns.len(), []),
sv_cities = array(cities.len(), [])
};
for(local l = 0; l < companies.len(); ++l)
{
data.sv_companies[l].append(companies[l].global_goal_id); // int
data.sv_companies[l].append(companies[l].tzgt); // array of int
data.sv_companies[l].append(companies[l].tzgtwns); //array of int
data.sv_companies[l].append(companies[l].id); // int
data.sv_companies[l].append(companies[l].my_town); // weak reference to reference of object of type 'Town', stored as int.
data.sv_companies[l].append(companies[l].gametype); // int
data.sv_companies[l].append(companies[l].score); // int
data.sv_companies[l].append(companies[l].score_quarter); // int
data.sv_companies[l].append(companies[l].hq); // TileIndex (int)
}
for(local l = 0; l < towns.len(); ++l)
{
if(typeof towns[l] == "Town"){
data.sv_towns[l].append(towns[l].id); // int
data.sv_towns[l].append(towns[l].start_population); // int
data.sv_towns[l].append(towns[l].supply_cargo); // array of int
data.sv_towns[l].append(towns[l].stocked_cargo); // array of int
data.sv_towns[l].append(towns[l].company); // CompanyID (int)
data.sv_towns[l].append(towns[l].metro); // bool
data.sv_towns[l].append(towns[l].num_signs); // int
data.sv_towns[l].append(towns[l].cargo_signs); // array of SignID(int)
data.sv_towns[l].append(towns[l].basicsign); // SignID(int)
data.sv_towns[l].append(towns[l].muncipalities); // array of TownID(int)
data.sv_towns[l].append(towns[l].ismuncipality);} // bool
}
for(local l = 0; l < cities.len(); ++l)
{
if(typeof cities[l] == "City"){
data.sv_cities[l].append(cities[l].id); // int
data.sv_cities[l].append(cities[l].mult); // float
data.sv_cities[l].append(cities[l].sign_id); // SignID (int)
}
}
return data;
}
EDIT: This code doesn't work because of the single float element. This means I need to somehow save this data differently. How is the question.
Who is online
Users browsing this forum: No registered users and 9 guests