预加载
预加载
是一种提高数据读取性能的工具。通过在命令中批量调用预加载
,可以显著缩短读取数据的时长,提高性能。玩家数据
这是一个简单的例子:
for (var 玩家id of 玩家id列表) {
var 玩家变量 = 查找玩家(玩家id);
玩家变量.发送未读消息(玩家变量.名字 + '的金钱:' + 玩家变量.属性.金钱 + ',所在位置:' + 玩家变量.位置);
}
在这段代码中,我们向
玩家id列表
中的所有玩家依次发送未读消息。其中加载了玩家的名字、属性和位置数据。在循环中,代码要依次读取每个玩家的名字、属性和位置,这导致代码的运行时长变长。
而通过
玩家.预加载.xxx
,可以预加载玩家数据。例如:for (var 玩家id of 玩家id列表) {
var 玩家变量 = 查找玩家(玩家id);
玩家变量.预加载.名字;
玩家变量.预加载.属性.金钱;
玩家变量.预加载.位置;
}
// 预加载玩家的数据后,数据读取性能会显著提升
for (var 玩家id of 玩家id列表) {
var 玩家变量 = 查找玩家(玩家id);
玩家变量.发送未读消息(玩家变量.名字 + '的金钱:' + 玩家变量.属性.金钱 + ',所在位置:' + 玩家变量.位置);
}
在这个例子中,我们在读取玩家数据前,先调用预加载。“预加载”用于告诉系统,我们将要使用这些数据。系统会数据被使用前,一次性读取这些数据,后续使用这些数据时,则不需要依次加载它们,减少了运行时长。
数据库
这是一个关于数据库的例子:
var 总金钱 = 0;
for (var 玩家id of 玩家id列表) {
总金钱 += 数据.读(['玩家', 玩家id, '金钱']);
}
在这段代码中,我们希望计算
玩家id列表
中的所有玩家的总金钱,其中读取了数据库的特定路径。在循环中,数据库要依次读取每个玩家所对应的路径。而通过
数据.预加载.读([xxx])
,可以预加载数据库特定路径。例如:for (var 玩家id of 玩家id列表) {
数据.预加载.读(['玩家', 玩家id, '金钱']);
}
// 预加载数据库后,数据读取性能会显著提升
var 总金钱 = 0;
for (var 玩家id of 玩家id列表) {
总金钱 += 数据.读(['玩家', 玩家id, '金钱']);
}
这时,数据库的读取性能将得到显著提升。
性能
预加载
可以显著提升数据批量读取时的性能。例如,下面这段代码大概需要执行 200~300 毫秒。
for (let i = 0; i < 500; i++) {
数据.读(['测试路径', i]);
}
经过
预加载
优化后,这段代码用时 50~70 毫秒。for (let i = 0; i < 500; i++) {
数据.预加载.读(['测试路径', i]);
}
for (let i = 0; i < 500; i++) {
数据.读(['测试路径', i]);
}
由此可见,
预加载
对性能的优化是非常明显的。后续,随着 Realm 的不断更新,未来还有可能进一步缩短这段代码的运行时长。使用场景
从上面的例子可以看出,
预加载
适合有批量数据读取的场景。例如,在组件中显示列表、批量读取用户的信息等。需要注意的是,预加载只有在连续调用的情况下才会提高性能,下面这种代码是无法提高性能的:
// 错误示例
var 总金钱 = 0;
for (var 玩家id of 玩家id列表) {
数据.预加载.读(['玩家', 玩家id, '金钱']);
总金钱 += 数据.读(['玩家', 玩家id, '金钱']);
}
像上述代码
预加载.读
-> 读
-> 预加载.读
-> 读
... 这么依次调用是错误的。同理,如果只是读取一个数据,那么预加载这个数据也不会有性能提升。此外,
预加载
命令没有返回值,不能直接使用:// 错误示例
var 总金钱 = 0;
for (var 玩家id of 玩家id列表) {
总金钱 += 数据.预加载.读(['玩家', 玩家id, '金钱']);
}
“预加载”的效果会在脚本运行结束前一直生效,因此每个数据只需要预加载一次。例如,组件顶部的变量代码执行了“预加载”,后续的变量代码、子组件都会生效。在函数中的“预加载”也会在函数外生效。条件、动作、单次延迟执行、对外接口等脚本也同样适用。
“预加载”可以被重复调用,不会有额外影响。但循环代码本身具有一定的运行时长,因此最好避免重复调用“预加载”。
如果已经通过普通命令加载了数据,调用相应数据的“预加载”则不会有额外效果。
在使用“预加载”时,可以先对代码性能进行测试,确保使用“预加载”后有性能提升,避免不必要的冗余代码。