大模型加载策略-分片下载

分片下载的整体思路如下:

  1. 发起HEAD请求,确认资源大小
  2. 发起分片下载请求, 组合buffer, 解析资源

注意事项:

  1. 分片下载需要服务端支持,Aliyun Oss和AWS都默认支持无需额外处理, 资源在自建服务器的可以自行实现
  2. 下文的分片下载基于Aliyun Oss方式实现

正文:

  1. 由于不同环境不同设备计算模型大小的方式不一致,由客户端发起HEAD请求,获取报头, 确认资源文件大小的方式是比较靠谱的选择,这个过程大约在30ms内.
[code] [javascript]
1
2
3
4
5
6
7
8
9
const request = new XMLHttpRequest();
request.open( 'HEAD', url, true );
request.onreadystatechange = () => {
if( request.status === 200 ){
let size = request.getResponseHeader('Content-Length');
console.log(size);
}
}
request.send();


HEAD请求会返回Content-Length字段
  1. 分片下载一般通过request header中的Range字段来告诉服务端需要的chunk range,
    在http1.x中chrome的并发请求数是6,我们一般用6x倍作为chunk number.
[code] [javascript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const chunkNum = 6; //这里我写死6,可根据业务情况自行决定
const chunkSize = Math.ceil(size / chunkNum);
const jobs = [];

//创建6个请求任务,给每个任务的分配的range是不同的
for( let i = 0, len = chunkNum; i < len; i++ ) {
let start = i * chunkSize;
let end = ( i + 1 ) * chunkSize - 1;
jobs.push(
httpGet( url, {
responseType: 'blob',
headers: {
Range: `bytes=${start}-${end}`
}
}) //status: 206
)
}

Promise.all( jobs ).then( async data => {
//将blob数组转换为arraybuffer
let arraybuffer = await (new Blob( data ).arrayBuffer());
console.log(arraybuffer);
gltfLoader.parse( arraybuffer, ... );
});


可以看到2.4M的模型被分成6个chunk并行加载