返回

异步分片计算在腾讯文档的实践,提升FPS,流畅操作更轻松

前端

背景

几个月前,我们对腾讯文档 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())