3

I'm creating compression and decompression app which are using xz compression method. But the compression and decompression are slower compared to another app which also uses the same compression method. For example, I have tried to decompress 15mb file into 40mb file and my code takes about 18 seconds, while it only takes about 4 seconds on another app.

I'm using XZInputStream from XZ for Java and TarArchiveInputStream from Apache Common Compress

public static void decompress(File file, String targetPath) {
    try {
        File outputFile = new File(targetPath);
        FileInputStream fileInputStream = new FileInputStream(file);
        XZInputStream xzInputStream = new XZInputStream(fileInputStream);
        TarArchiveInputStream tarInputStream = new TarArchiveInputStream(xzInputStream);
        TarArchiveEntry entry;
        while ((entry = tarInputStream.getNextTarEntry()) != null) {
            if (entry.isDirectory()) {
                continue;
            }
            File curFile = new File(outputFile, entry.getName());
            File parent = curFile.getParentFile();
            if (!parent.exists()) {
                parent.mkdirs();
            }
            IOUtils.copy(tarInputStream, new FileOutputStream(curFile));
        }
    } catch (FileNotFoundException e) {
        Log.e("Exception", Log.getStackTraceString(e));
    } catch (IOException e) {
        Log.e("Exception", Log.getStackTraceString(e));
    }
}
Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98

1 Answers1

0

I do not know about the performance of the library that you are using. However, I can just drop my suggestions here which might help you to improve the performance.

Looks like you are blocking the UI thread using this large operation inside your while loop. I would like to suggest you create an AsyncTask and then put the code there in the doInBackground function which will not block the UI thread and the operation will be taken care of with a background thread.

Speaking of using a background thread. You might also consider using multiple threads to decompress your file. I am not sure about how this can be done, however, I might suggest an idea like the following.

while ((entry = tarInputStream.getNextTarEntry()) != null) {
    if (entry.isDirectory()) continue;

    File curFile = new File(outputFile, entry.getName());
    File parent = curFile.getParentFile();
    if (!parent.exists()) {
        parent.mkdirs();
    }

    // Create a thread for each of these operations and do it in background. 
    // Thus you can take the advantage of using multiple threads to process your operations faster
    // Instead of passing the whole tarInputStream, just pass the entry and check if that works.
    IOUtils.copy(entry, new FileOutputStream(curFile));
}

Hope that helps!

Update

I think copying from the InputStream is taking much time and hence you can consider putting a BufferedInputStream in the middle of these like the following.

FileInputStream fileInputStream = new FileInputStream(file);
BufferedInputStream bin = new BufferedInputStream(fileInputStream); 
XZInputStream xzInputStream = new XZInputStream(bin);
Reaz Murshed
  • 23,691
  • 13
  • 78
  • 98
  • I have placed the code in an asynctask already, thanks btw. I also thought of using multiple threads, but the library itself is not well-documented, which is why i don't know how to implement it. – Eric Kantana Apr 26 '19 at 03:49
  • Hi, I have updated the answer. Please check if that can be done and then you can split your code into multiple threads. – Reaz Murshed Apr 26 '19 at 03:53
  • I don't think the problem is on writing out the entry. I just tried to calculate the execution time and it seems the getNextTarEntry() is the method that takes the most time to execute. – Eric Kantana Apr 26 '19 at 04:11
  • That's interesting. Let me search for this a little bit more. – Reaz Murshed Apr 26 '19 at 04:16
  • Please check the updated answer. Put the `BufferedInputStream` around like stated in the answer. – Reaz Murshed Apr 26 '19 at 04:26
  • I have tried it already as another person have suggested. But it didn't give me any performance improvement at all. – Eric Kantana Apr 26 '19 at 04:42
  • I tried to remove the XZInputStream and read ordinary tar file without xz compression instead and it does read the tar file very quick. I also tried XZCompressorInputStream from apache common compress, but it also very slow to read the .tar.xz file. – Eric Kantana Apr 26 '19 at 04:48