itinance / react-native-fs

Native filesystem access for react-native
MIT License
4.91k stars 963 forks source link

Read/write extremely slow on Android #388

Open bitfabrikken opened 6 years ago

bitfabrikken commented 6 years ago

I'm not sure exactly what's going on, but shouldn't writing/reading files be significantly faster than the below quick test? And shouldn't read by faster than write, not slower?

I think I might be doing something wrong.

The reason I'm asking is that I've got a pretty big JSON object, around 4 MB, I need to store in the app. And since it's > 2 MB I can't use AsyncStorage on Android. So I want to save it to a file, and read it on startup of the app. But the loading time of several seconds isn't gonna fly with the user base.

result on a new, clean Pixel 2.

11-18 12:26:10.726  5592  7953 I ReactNativeJS: str is 4198400 bytes (4.00 MB)
11-18 12:26:10.726  5592  7953 I ReactNativeJS: starting write
11-18 12:26:14.381  5592  7953 I ReactNativeJS: write done in 3.654 (1.10 MB/s)
11-18 12:26:14.381  5592  7953 I ReactNativeJS: starting read
11-18 12:26:21.333  5592  7953 I ReactNativeJS: read done in 6.951 (0.58 MB/s)
var RNFS = require('react-native-fs');

var file = {
    test: async function(){

        var uri = RNFS.DocumentDirectoryPath + "/test.txt";

        //generate str
        var str = "";
        for (var i=0;i<1024;i++) {
            str += "a";
            for (var n=0;n<1024;n++) {
                str += "b";
            }
        }
        str += "";
        var megs = str.length / 1024 / 1024;
        console.log(`str is ${str.length} bytes (${megs.toFixed(2)} MB)`);

        //write test
        var now = Date.now();
        console.log("starting write");
        await RNFS.writeFile(uri, str);
        var secs = (Date.now() - now)/1000;
        console.log(`write done in ${secs} (${(megs/secs).toFixed(2)} MB/s)`);

        //read test
        now = Date.now();
        debug.dd("starting read");
        str = await RNFS.readFile(uri);
        secs = (Date.now() - now)/1000;
        console.log(`read done in ${secs} (${(megs/secs).toFixed(2)} MB/s)`);

    }
};

await file.test();
bitfabrikken commented 6 years ago

Must be the default utf-8 encoding. I just tried using base64, which turned out to be at least 10 times faster.

nevir commented 6 years ago

You might also want to take a look at https://github.com/wkh237/react-native-fetch-blob (we find it consistently about 20x faster when than rn-fs on android, when reading - regardless of encoding)

esprehn commented 6 years ago

We were loading 900kb of JSON from a file and it was taking 600ms inside readFile. We switched to react-native-fetch-blob and it's 60ms now so at least 10x faster. It also appears that react-native-fs is doing the utf8 encoding/base64 encoding inside JS which blocks the JS thread for a long period of time making the app feel frozen.

alainib commented 6 years ago

i'm writing a 5mb json in a file with utf8 encoding. it take +-50ms with android it take +-6000ms with ios iphone 5

reading the file take 250ms with android, more than 13000ms with ios. I need to keep utf8, any advice ?

kesha-antonov commented 5 years ago

Is this solved? Seems like encoding is done on js side

alainib commented 5 years ago

i need to read a jpg file (8 or 9mb sometimes) to extract the exif. i need it to je in base64, it take 3s with fetch blob, too long. it this normal ? thanks

maxkomarychev commented 5 years ago

this is all due encoding that is done on js side. rnfs does coding in js https://github.com/itinance/react-native-fs/blob/master/FS.common.js#L158-L166 the competing rnfb does this in native https://github.com/joltup/rn-fetch-blob/blob/master/ios/RNFetchBlobFS.m#L506-L531

I had to switch to rnfb, reading large json files is around 10-100 times faster now this is also true for ios btw