Skip to content

Commit 4dc0d40

Browse files
committed
add chunk size parameter for wasm fetchfs, fix bugs
1 parent c919046 commit 4dc0d40

File tree

5 files changed

+122
-15
lines changed

5 files changed

+122
-15
lines changed

src/library_fetchfs.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ addToLibrary({
88
$FETCHFS__deps: ['$stringToUTF8OnStack', 'wasmfs_create_fetch_backend'],
99
$FETCHFS: {
1010
createBackend(opts) {
11-
return _wasmfs_create_fetch_backend(stringToUTF8OnStack(opts.base_url));
11+
return _wasmfs_create_fetch_backend(stringToUTF8OnStack(opts.base_url), opts.chunkSize | 0);
1212
}
1313
},
1414
});

src/library_wasmfs_fetch.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,17 @@ addToLibrary({
3434
} catch (e) {
3535
}
3636
}
37-
var chunkSize = __wasmfs_fetch_get_chunk_size();
37+
var chunkSize = __wasmfs_fetch_get_chunk_size(file);
3838
offset = offset || 0;
3939
len = len || chunkSize;
4040
var firstChunk = (offset / chunkSize) | 0;
4141
var lastChunk = ((offset+len) / chunkSize) | 0;
4242
if (!(file in wasmFS$JSMemoryRanges)) {
43-
var fileInfo = await fetch(url,{method:"HEAD",headers:{"Range":"bytes=0-1"}});
44-
if(fileInfo.ok && fileInfo.headers.has("Content-Length") && fileInfo.headers.get("Accept-Ranges") == "bytes" && (parseInt(fileInfo.headers.get("Content-Length")) > chunkSize*2)) {
43+
var fileInfo = await fetch(url,{method:"HEAD", headers:{"Range": "bytes=0-"}});
44+
if(fileInfo.ok &&
45+
fileInfo.headers.has("Content-Length") &&
46+
fileInfo.headers.get("Accept-Ranges") == "bytes" &&
47+
(parseInt(fileInfo.headers.get("Content-Length")) > chunkSize*2)) {
4548
wasmFS$JSMemoryRanges[file] = {size:parseInt(fileInfo.headers.get("Content-Length")), chunks:[], chunkSize:chunkSize};
4649
} else {
4750
// may as well/forced to download the whole file
@@ -74,11 +77,11 @@ addToLibrary({
7477
// This is the first time we want the chunk's data.
7578
var start = firstChunk*chunkSize;
7679
var end = lastChunk*chunkSize;
77-
var response = await fetch(url, {headers:{"Range": `bytes=${start}-${end}`}});
80+
var response = await fetch(url, {headers:{"Range": `bytes=${start}-${end-1}`}});
7881
if (response.ok) {
7982
var bytes = new Uint8Array(await response['arrayBuffer']());
8083
for (i = firstChunk; i < lastChunk; i++) {
81-
wasmFS$JSMemoryRanges[file].chunks[i] = bytes.slice(i*chunkSize,(i+1)*chunkSize);
84+
wasmFS$JSMemoryRanges[file].chunks[i] = bytes.slice(i*chunkSize-start,(i+1)*chunkSize-start);
8285
}
8386
} else {
8487
throw response;
@@ -125,8 +128,8 @@ addToLibrary({
125128
if(!chunk) {
126129
throw [fileData.length, firstChunk, lastChunk, i];
127130
}
128-
var end = Math.min(start+chunk.byteLength, offset+length);
129131
var chunkStart = i*chunkSize;
132+
var end = Math.min(chunkStart+chunkSize, offset+length);
130133
HEAPU8.set(chunk.subarray(start-chunkStart, end-chunkStart), buffer+(start-offset));
131134
readLength = end - offset;
132135
}

system/include/emscripten/wasmfs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ backend_t wasmfs_create_memory_backend(void);
5757
//
5858
// TODO: Add an async version of this function that will work on the main
5959
// thread.
60-
backend_t wasmfs_create_fetch_backend(const char* base_url __attribute__((nonnull)));
60+
backend_t wasmfs_create_fetch_backend(const char* base_url __attribute__((nonnull)), uint32_t);
6161

6262
backend_t wasmfs_create_node_backend(const char* root __attribute__((nonnull)));
6363

system/lib/wasmfs/backends/fetch_backend.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,14 +104,14 @@ uint32_t FetchBackend::getChunkSize() {
104104
}
105105

106106
extern "C" {
107-
backend_t wasmfs_create_fetch_backend(const char* base_url /* TODO manifest */) {
107+
backend_t wasmfs_create_fetch_backend(const char* base_url, uint32_t chunkSize /* TODO manifest */) {
108108
// ProxyWorker cannot safely be synchronously spawned from the main browser
109109
// thread. See comment in thread_utils.h for more details.
110110
assert(!emscripten_is_main_browser_thread() &&
111111
"Cannot safely create fetch backend on main browser thread");
112112
return wasmFS.addBackend(std::make_unique<FetchBackend>(
113113
base_url ? base_url : "",
114-
DEFAULT_CHUNK_SIZE,
114+
chunkSize != 0 ? chunkSize : DEFAULT_CHUNK_SIZE,
115115
/* TODO manifest */
116116
[](backend_t backend) { _wasmfs_create_fetch_backend_js(backend); }));
117117
}

test/wasmfs/wasmfs_fetch.c

Lines changed: 109 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ void check_file(int fd, const char* content) {
4242
void test_url_relative() {
4343
printf("Running %s...\n", __FUNCTION__);
4444

45-
backend_t backend2 = wasmfs_create_fetch_backend("test.txt");
45+
backend_t backend2 = wasmfs_create_fetch_backend("test.txt",0);
4646
int fd = wasmfs_create_file("/file_rel", 0777, backend2);
4747
check_file(fd, "fetch 2");
4848
assert(close(fd) == 0);
@@ -56,7 +56,7 @@ void test_url_absolute() {
5656
char url[200];
5757
snprintf(url, sizeof(url), "%s%s", url_orig, file_name);
5858

59-
backend_t backend = wasmfs_create_fetch_backend(url);
59+
backend_t backend = wasmfs_create_fetch_backend(url,0);
6060
int fd = wasmfs_create_file(file_name, 0777, backend);
6161
check_file(fd, "fetch 2");
6262
assert(close(fd) == 0);
@@ -69,7 +69,7 @@ void test_directory_abs() {
6969
char url[200];
7070
snprintf(url, sizeof(url), "%s%s", url_orig, dir_path);
7171

72-
backend_t backend = wasmfs_create_fetch_backend(url);
72+
backend_t backend = wasmfs_create_fetch_backend(url,0);
7373
int res = wasmfs_create_directory(dir_path, 0777, backend);
7474
if (errno)
7575
perror("wasmfs_create_directory");
@@ -100,7 +100,7 @@ void test_directory_abs() {
100100

101101
void test_default() {
102102
printf("Running %s...\n", __FUNCTION__);
103-
backend_t backend = wasmfs_create_fetch_backend("data.dat");
103+
backend_t backend = wasmfs_create_fetch_backend("data.dat",0);
104104

105105
// Create a file in that backend.
106106
int fd = wasmfs_create_file("/testfile", 0777, backend);
@@ -136,7 +136,7 @@ void test_small_reads() {
136136
char expected[] = "hello";
137137
size_t size = 5;
138138

139-
backend_t backend = wasmfs_create_fetch_backend("small.dat");
139+
backend_t backend = wasmfs_create_fetch_backend("small.dat",0);
140140
int fd = wasmfs_create_file("/testfile3", 0777, backend);
141141
char buf[size + 1];
142142
for (size_t i = 0; i < size; i++) {
@@ -150,6 +150,108 @@ void test_small_reads() {
150150
assert(close(fd) == 0);
151151
}
152152

153+
void test_small_chunks() {
154+
// Read the file in small amounts.
155+
printf("Running %s...\n", __FUNCTION__);
156+
157+
char expected[] = "hello";
158+
size_t size = 5;
159+
160+
backend_t backend = wasmfs_create_fetch_backend("small.dat",2);
161+
int fd;
162+
char buf[size + 1];
163+
fd = wasmfs_create_file("/testfile4", 0777, backend);
164+
for (size_t i = 0; i < size; i+=1) {
165+
int read_now = read(fd, buf + i, 1);
166+
assert(read_now <= 1);
167+
printf("read some bytes smaller than chunk size\n");
168+
}
169+
buf[size] = 0;
170+
printf("buf %s\n",buf);
171+
assert(strcmp(buf, "hello") == 0);
172+
173+
assert(close(fd) == 0);
174+
175+
fd = wasmfs_create_file("/testfile5", 0777, backend);
176+
for (size_t i = 0; i < size; i+=2) {
177+
int read_now = read(fd, buf + i, 2);
178+
assert(read_now <= 2);
179+
printf("read some bytes equal to chunk size\n");
180+
}
181+
buf[size] = 0;
182+
printf("buf %s\n",buf);
183+
assert(strcmp(buf, "hello") == 0);
184+
185+
assert(close(fd) == 0);
186+
187+
fd = wasmfs_create_file("/testfile6", 0777, backend);
188+
for (size_t i = 0; i < size; i+=5) {
189+
int read_now = read(fd, buf + i, 5);
190+
assert(read_now <= 5);
191+
printf("read some bytes much larger than chunk size\n");
192+
}
193+
buf[size] = 0;
194+
printf("buf %s\n",buf);
195+
assert(strcmp(buf, "hello") == 0);
196+
197+
assert(close(fd) == 0);
198+
}
199+
200+
void test_small_chunks_divisor_of_size() {
201+
printf("Running %s...\n", __FUNCTION__);
202+
203+
char expected[] = "hello, fetch";
204+
size_t size = 12;
205+
206+
backend_t backend = wasmfs_create_fetch_backend("data.dat",4);
207+
int fd;
208+
char buf[size + 1];
209+
fd = wasmfs_create_file("/testfile7", 0777, backend);
210+
for (size_t i = 0; i < size; i+=3) {
211+
int read_now = read(fd, buf + i, 3);
212+
assert(read_now <= 3);
213+
printf("read some bytes less than chunk size\n");
214+
}
215+
buf[size] = 0;
216+
printf("buf %s\n",buf);
217+
assert(strcmp(buf, "hello, fetch") == 0);
218+
assert(close(fd) == 0);
219+
220+
fd = wasmfs_create_file("/testfile8", 0777, backend);
221+
for (size_t i = 0; i < size; i+=4) {
222+
int read_now = read(fd, buf + i, 4);
223+
assert(read_now <= 4);
224+
printf("read some bytes equal to chunk size\n");
225+
}
226+
buf[size] = 0;
227+
printf("buf %s\n",buf);
228+
assert(strcmp(buf, "hello, fetch") == 0);
229+
230+
assert(close(fd) == 0);
231+
232+
fd = wasmfs_create_file("/testfile9", 0777, backend);
233+
for (size_t i = 0; i < size; i+=5) {
234+
int read_now = read(fd, buf + i, 5);
235+
assert(read_now <= 5);
236+
printf("read some bytes greater than chunk size\n");
237+
}
238+
buf[size] = 0;
239+
printf("buf %s\n",buf);
240+
assert(strcmp(buf, "hello, fetch") == 0);
241+
242+
assert(close(fd) == 0);
243+
244+
fd = wasmfs_create_file("/testfile10", 0777, backend);
245+
int read_now = read(fd, buf, 12);
246+
assert(read_now == 12);
247+
printf("read some bytes much greater than chunk size\n");
248+
buf[size] = 0;
249+
printf("buf %s\n",buf);
250+
assert(strcmp(buf, "hello, fetch") == 0);
251+
252+
assert(close(fd) == 0);
253+
}
254+
153255
void test_nonexistent() {
154256
printf("Running %s...\n", __FUNCTION__);
155257

@@ -185,6 +287,8 @@ int main() {
185287
test_url_absolute();
186288
test_directory_abs();
187289
test_small_reads();
290+
test_small_chunks();
291+
test_small_chunks_divisor_of_size();
188292
test_nonexistent();
189293

190294
return 0;

0 commit comments

Comments
 (0)