需求:游戏中热更新下载的散文件很多,单个线程的下载速度非常慢,在这一环节上用户流失严重,决定使用多个Http下载线程,同时写入文件。
当前下载逻辑分析:
游戏中使用的libcurl库,主线程开启一个独立的Http线程,两者之间的关系如下:
MainThread HttpThread
新的request放入请求队列(加锁) 从request队列取出发送(加锁)
Update刷新界面 将response加入到响应队列(加锁)
从响应队列取出response(加锁)
调用callback传递response
往磁盘里写入下载的文件流
新的下载逻辑分析:
多个HttpThread的情况,脚本配置启动的线程数,默认开启5个线程:
MainThread 每个HttpThread
request提前分配到各个线程队列 从自己的request队列取出发送(提前分配过了,不需要加锁)
根据当前进度数据Update界面 response不需要加入到响应队列
直接调用callback,往磁盘写文件,创建目录的代码段加锁
修改进度数据(加锁)
注意事项:
1.所有调用的共享静态变量全局变量,单例,LuaStack的线程安全和加锁读写
2.WriteBufferToDisk往磁盘写文件的线程安全
3.libcurl是线程安全的,但是curl_global_init(CURL_GLOBAL_ALL)只能预先调用一次,在主线程中单独调用,该函数不是线程安全的。每个线程使用独立的CURL *curl; curl_easy_setopt(CURLOPT_NOSIGNAL,1)必须设置为1.
最终多线程下载测试数据:
Windows平台:
下载322M散文件,单个线程耗费 310秒,开5个线程耗费 39秒,开10个线程耗费 32秒,游戏中默认开启5个线程,效率提升8倍左右
Android平台:
下载105M散文件,单个线程耗费 637秒,开5个线程耗费 29秒,开10个线程耗费 20秒,游戏中默认开启5个线程,效率提升21倍左右