返回
异步分片计算在腾讯文档的实践,提升FPS,流畅操作更轻松
前端
2024-02-03 19:43:42
背景
几个月前,我们对腾讯文档 Smart Sheet 中的看板视图排版计算进行了一次优化,这次优化主要是利用异步分片计算来提高当前的 FPS 值,避免用户操作被阻塞,让用户操作更流畅。在这里,感谢kylehr的支持和帮助。
挑战
1. FPS不稳定,用户操作卡顿
在之前的实现中,看板视图的排版计算是在主线程上进行的。当数据量较大时,计算量会很大,导致主线程卡顿,进而导致FPS下降。
2. 代码复杂,可维护性差
之前的代码实现非常复杂,可维护性差。当需要修改或添加新功能时,会非常困难。
解决方案
为了解决上述问题,我们采用了异步分片计算的方案。具体来说,我们对看板视图的排版计算进行了以下优化:
1. 将计算任务拆分成多个小任务
我们将看板视图的排版计算任务拆分成多个小任务,并将其分配给多个线程并行执行。这样,就可以避免主线程被阻塞,从而提高FPS。
2. 使用消息队列进行任务通信
我们将任务分配给不同的线程后,需要一种机制来让这些线程之间进行通信。我们使用消息队列来实现这一目的。
3. 使用原子计数器保证计算结果的正确性
因为使用了异步分片计算,所以我们需要保证计算结果的正确性。我们使用原子计数器来保证这一点。
效果
经过优化的异步分片计算方案后,看板视图的FPS值有了显著的提升。在数据量较大的情况下,FPS值可以保持在60以上,用户操作非常流畅。
总结
异步分片计算是一种非常有效的优化技术,它可以帮助我们提高程序的性能。在腾讯文档中,我们成功地将异步分片计算应用到了看板视图的排版计算中,并取得了非常好的效果。
代码示例
import asyncio
import concurrent.futures
async def async_task(task_id, data):
"""
异步任务
"""
result = 0
for i in data:
result += i
return task_id, result
async def main():
"""
主函数
"""
# 创建线程池
executor = concurrent.futures.ThreadPoolExecutor(max_workers=4)
# 创建消息队列
queue = asyncio.Queue()
# 创建任务列表
tasks = []
for i in range(10):
data = list(range(10000))
task = asyncio.ensure_future(async_task(i, data))
tasks.append(task)
# 将任务分配给线程池
for task in tasks:
loop.run_in_executor(executor, task.send, None)
# 从消息队列中获取计算结果
while not tasks:
task_id, result = await queue.get()
print(f"Task {task_id} completed with result: {result}")
# 启动事件循环
loop = asyncio.get_event_loop()
loop.run_until_complete(main())