Page 1 of 1
Too long to save
Posted: 18 Oct 2012 10:19
by Aphid
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).
Re: Too long to save
Posted: 18 Oct 2012 11:01
by Yexo
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
Posted: 07 Dec 2012 12:34
by Aphid
I've been experimenting a lot, but how to do it even faster than this?
Code: Select all
function Scriptname::Save(){return{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?
Re: Too long to save
Posted: 07 Dec 2012 13:30
by Aphid
Even something like
Code: Select all
function ScriptName::Save(return data;)
won't work.
(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.
Re: Too long to save
Posted: 07 Dec 2012 14:09
by Yexo
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
Posted: 07 Dec 2012 16:12
by Aphid
The first returns a table. Syntax for table (size n) is:
my_table = {
entry_1 = var_1
...
entry_n = var_n}
entry_i and var_i can be any variable name of any type.
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.
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;
}
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.