-
Notifications
You must be signed in to change notification settings - Fork 143
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
忽然想到一个效率低下 但是能解决 key=table pairs异步的解决方案 #214
Comments
最简单的办法不是避免这种用法吗 |
你脱离作图1线 异步创建table 是很难避免的, 除非将所有异步的接口分离,单独一个虚拟机, 同步接口单独一个虚拟机, 否则一定存在异步创建table的情况的, 比如 message.hook 你自己就异步创建了table push给lua了。。。 |
我是说避免遍历key是gc对象的table |
总是会有这种需求的。 再者遍历 key=string是硬需求, 但是在编写过程中很容易疏忽 导致一个表里 不止是string 有可能存在其他的obj 这时候就异步了。 lua产生异步的概率还是非常高的 |
key是string,只需要统一string的hash值就可以解决 |
我知道, 但是在编写的过程中,很容易疏忽, 让一个表的key不完全是string ,而且一些新人入坑的 完全不知道这个问题,在编写完几万行代码后发现地图异步,几乎如同海底捞针。 |
检查pairs和next,不符合要求就抛错 |
这是不得以而为之的办法。 dream big |
就1楼的方案 专门看了一下 luaL_traceback 的源码 发现效率低的原因有2个 1 字符串格式化 字符串连接 这些操作 所以针对这2个问题 去掉一些无用信息 就遍历调用栈 取关键信息进行哈希 节省字符串格式化/连接 这些操作 就可以极大的提高 获取调用栈哈希值 信息的效率。 应该还是可行性的 等后面有空的时候我再实际操作一个版本试试。 |
同位置也会有异步的table鸭 local res
for i = 1, jass.GetPlayerID(jass.GetLocalPlayer()) do
res = {}
end 实际业务中,可能是一个异步的事件执行同一段代码,然后将创建的表保存在全局里以后用。 |
异步创建的表 混合 同步创建的表 一起作为key 进行遍历 产生的异步 确实可能存在,但是情况还是会比较少的, 大部分情况下 是在同步环境下 创建的表对象 需要在同步的情况下进行pairs 仅仅为满足这个需求。 当然最安全的情况 就是分2个虚拟机 用中间代码进行交互。 但是会带来使用上的负担 影响便捷性 |
我觉得,与其做一个99%安全的功能,不如完全禁止这个功能。英萌当年就做了 |
pairs之所以异步 是因为 没办法给table分配一个 所有玩家都一致的 index,
1.32 在每个table创建时 自动分配一个独立的index ,但是因为本地玩家/异步事件 会在异步时机创建table,进而导致之后分配的索引异步,从而失败,
所以问题的本质 就是 每个table 需要一个不受其他位置创建table的影响, 而在自己的位置有自己的计数的一个index
所以我想到的解决方案就是 在创建table时, 根据当前lua堆栈 获取一个索引分配器, 进行递增分配索引
所以 最终结果是 index的类型 由 uint64_t 来完成
uint64_t 高位 4字节 由lua调用堆栈 进行哈希算法 由4字节哈希值完成
uint64_t 低位 4字节 由lua调用堆栈 映射的分配器 进行递增 来完成
这样异步环境下 调用 某个函数 生成的table
跟同步环境下 调用 同一个函数 生成的table 他们之间的 index 都是分别独立 不会互相干扰
这样同步产生的table 作为key 进行遍历 就不会异步了
这个方案唯一的问题就是 获取lua调用堆栈的效率过低, 尤其是 lua5.3之后 debug.traceback的效率 相比5.1下降了10倍 所以差最后这个步骤进行闭环。
The text was updated successfully, but these errors were encountered: