Titanium JIRA Archive
Titanium SDK/CLI (TIMOB)

[TIMOB-15756] Android: Ti.File.exists() slow performance

GitHub Issuen/a
TypeNew Feature
PriorityHigh
StatusOpen
ResolutionUnresolved
Affected Version/sRelease 3.1.3
Fix Version/sn/a
ComponentsAndroid
LabelsSupportTeam
ReporterVladimir S
AssigneeUnknown
Created2013-11-04T18:36:32.000+0000
Updated2018-02-28T20:04:04.000+0000

Description

Problem Description

I just noticed that calling Ti.File.exists() on a file that is missing is quite costly in Android (on Galaxy S4). The folder contains only one file, and I am trying Ti.Filesystem.getFile('wrongfile').exists(). It takes 500-600 ms for this call to complete. In comparison Ti.Filesystem.getFile('wrongfile').getSize() returns 0 immediately.

Workaround

Use Ti.Filesystem.getFile('wrongfile').getSize() instead of exists

Comments

  1. Motiur Rahman 2013-11-05

    Hi Vladimir S, Could you share some simple app.js code so that i reproduce this issue. Thanks,
  2. Philippe Wueger 2014-05-27

    The TiResourceFile exists() method does a directory listing if the file does not exist in order to check if the file is a directory. This directory listing seems to be slow (maybe only on large directories). Possible solutions within the Titanium framework: 1. Add an (optional) argument "checkForDirectories" to the exists method and only check for directory if really needed 2. Check if there are more efficient solutions to see if a file is an existing directory
  3. Ingo Muschenetz 2014-05-27

    [~philet] Can you give an example of what is slow? What is the difference between a file in a directory with only one file and a directory with 1000 files.
  4. Philippe Wueger 2014-06-10

    Hi Ingo On a Galaxy Nexus Phone with SDK 3.2.3 it does not seem to make a difference if a directory with 1000 files is checked or a directory with 1 file. If the file does not exist, it is slow (around ~70ms). If the file exists, it is fast (<1ms). See my code and the results below. Thanks & Regards, Philippe app.js
       var directoryWith1000Files = 'oneFile';
       var directoryWith1File = 'thousandFiles';
       var existingFile = 'i-do-exist.txt';
       var nonExistentFile = 'i-do-not-exist.txt';
       
       function measure(directory, fileName) {
       	for (var i=0; i < 10; i++) {
       		var file = Ti.Filesystem.getFile(directory, fileName);
       		var t1 = new Date();
       		var result = file.exists();
       		var t2 = new Date();
       		Ti.API.info(String.format('TIME (ms): %d | %s | %s', t2.getTime() - t1.getTime(), result ? 'EXISTS' : 'DOES NOT EXIST', file.nativePath));
       	};	
       }
       
       Ti.API.info("directoryWith1File / existingFile:");
       measure(directoryWith1File, existingFile);
       
       Ti.API.info("directoryWith1000Files / existingFile:");
       measure(directoryWith1000Files, existingFile);
       
       Ti.API.info("directoryWith1File / nonExistentFile:");
       measure(directoryWith1File, nonExistentFile);
       
       Ti.API.info("directoryWith1000Files / nonExistentFile:");
       measure(directoryWith1000Files, nonExistentFile);
       
       
    Results:
       [INFO] :   TIME (ms): 3 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/thousandFiles/i-do-exist.txt
       [INFO] :   directoryWith1000Files / existingFile:
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   TIME (ms): 1 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   TIME (ms): 3 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   TIME (ms): 1 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   TIME (ms): 0 | EXISTS | file:///android_asset/Resources/oneFile/i-do-exist.txt
       [INFO] :   directoryWith1File / nonExistentFile:
       [INFO] :   TIME (ms): 88 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   TIME (ms): 77 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   TIME (ms): 85 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   TIME (ms): 72 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   TIME (ms): 79 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   TIME (ms): 68 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   TIME (ms): 66 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   TIME (ms): 67 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   TIME (ms): 70 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   TIME (ms): 66 | DOES NOT EXIST | file:///android_asset/Resources/thousandFiles/i-do-not-exist.txt
       [INFO] :   directoryWith1000Files / nonExistentFile:
       [INFO] :   TIME (ms): 66 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       [INFO] :   TIME (ms): 66 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       [INFO] :   TIME (ms): 78 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       [INFO] :   TIME (ms): 70 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       [INFO] :   TIME (ms): 86 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       [INFO] :   TIME (ms): 70 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       [INFO] :   TIME (ms): 67 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       [INFO] :   TIME (ms): 67 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       [INFO] :   TIME (ms): 66 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       [INFO] :   TIME (ms): 65 | DOES NOT EXIST | file:///android_asset/Resources/oneFile/i-do-not-exist.txt
       

JSON Source