16

I'm compiling my (fairly simple, just 5 files with few hundred LOC) app from command line on OSX using:

ant debug

It works. But it works slowly:

BUILD SUCCESSFUL Total time:

26 seconds

Why is that? It takes this much time even if I change only one line in one java file. Most of this time is spent in dex stage (about 20 seconds), which is AFAIK creating Dalvik bytecode. But my friend that also works on the same project on Windows using Eclipse says that compiling takes only a second or two on his machine. Is there anything I can do to speed up this proccess?

mav
  • 1,230
  • 1
  • 15
  • 23
  • What Apple has to do with Android build times? By the way, testing iOS is a breeze - from starting compilation to app running on simulator in just few seconds. – mav Aug 23 '12 at 10:56
  • you said that you run it on OSX, and you also said that your friend (on Windows) is compiling the same project in a second not (but in Eclipse) ... anyway did you try to use ant on windows platform? if it takes more time than compiling in eclipse than its ant problem if not ... problem is with your computer. – Selvin Aug 23 '12 at 11:36
  • I didn't try it on windows. Anyways, I know it's probably a problem with ant, because it's rebuilding dex files from scratch, whereas Eclipse caches it or something. That's why I asked the question - to know if there's a solution for that. I don't want to use Eclipse because it's slow and I hate the UI. – mav Aug 23 '12 at 18:19

2 Answers2

13

I finally found a solution for this! It's a bit of a hack, but it works.

First, go to your ANDROID-SDK/platform-tools directory, then rename dx app to something else, like dextool, and finally create new dx file with contents:

#!/bin/sh
shift
dextool --dex --incremental --no-optimize $@

Replace "dextool" with the name you chose before. This will prepend (undocumented) --incremental attribute to every dex invocation, which will massively decrease build times by dexing only classes that have changed between builds. Now it looks like this:

[dx] Merged dex A (1 defs/11,3KiB) with dex B (359 defs/1253,2KiB). Result is 359 defs/1519,3KiB. Took 0,5s

0.5s instead of 20s is a huge difference!

Edit - few remarks:

  • you have to compile your project at least once before using this, because it uses previous classes.dex file
  • you can run into problems when using other Android toolchains than ant

UPDATE:

Google released SDK Tools 21.0, which renders above tweak absolete, because it does supports pre-dexing. Finally!

Richard J. Ross III
  • 55,009
  • 24
  • 135
  • 201
mav
  • 1,230
  • 1
  • 15
  • 23
  • I really wish Google would fix this. It is a bit silly how long it takes to build from the ant script - for me, a clean and rebuild using ADT takes ~30 seconds where the build.xml ant script takes ~60 seconds. – Wayne Uroda Aug 30 '12 at 07:01
  • This actually works really well. I've been using it consistently for a couple of weeks now and the only downside I can see if you lose line numbers in stacktraces. Best to turn off for production but saves a lot of time in dev. – brk3 Oct 04 '12 at 20:34
  • 5
    Hi @mav, could you please clarify whether SDK Tools 21.0 will do this automatically, or requires configuration? I tried updating to latest (21.1), but my build times haven't significantly reduced, even if I change only one line. Using IntelliJ on Ubuntu – Alex May 02 '13 at 04:38
  • @mav I downloaded the latest android adt... I think there are also the last sdk tools... But I still get 30+ build time on local build with CLI... Is there another workareound because I cannot find dx app in ANDROID-SDK/platform-tools directory? – Alex Stanese Feb 08 '14 at 12:03
  • 1
    @AlexStanese: it's in SDK/build-tools/version. – TWiStErRob Nov 12 '14 at 16:36
  • @Alex I added a [new answer](http://stackoverflow.com/a/26891911/253468), which speeds up 21.1.1 builds as well. – TWiStErRob Nov 12 '14 at 16:37
  • `chmod +x path-to-new-dx` is also required. – suzanshakya Oct 19 '16 at 08:39
0

Even in 21.1.1 with the --incremental --no-optimize added in the original dex.bat it is slow, so I went on to figure something out, the result is: if you order the .jar files passed to dex by size you get better performance.

Watch https://code.google.com/p/android/issues/detail?id=79166 for updates, I hope they agree and this goes into vNext.

#!/usr/bin/perl
use strict;
use warnings;
#use Data::Dump qw(dump);
use List::Util qw(first), qw(sum);

# size of the argument, -s for files, -s on **/*.class for folders
sub size {
        if (-d $_) {
                # directory size is sum of all class files in the dir recursively
                # account for pre-dexing and compression with a 25% decrease
                return sum(map { size($_) * 0.25 } <$_/*.class>) || 0;
        }
        return -s $_; # use built-in size operator
}

my $dx_args_with_args =
   qr/^--(output|positions|(no-)?optimize-list|dump-(to|width|method)|num-threads|main-dex-list|input-list)$/;
my $nArgs = $#ARGV;
# last argument like --blah, those are for dx
my $lastArg = $nArgs - first { $ARGV[$nArgs - $_] =~ /^--/ } 0..$nArgs;
if ($lastArg != -1 && $ARGV[$lastArg] =~ /$dx_args_with_args/) {
        $lastArg += 1;
}

my @inputs = map { $_->[1] }
             sort { $a->[0] <=> $b->[0] }
             map { [size(), $_] }
             @ARGV[$lastArg + 1 .. $nArgs];

print join(" ", @ARGV[0..$lastArg], @inputs);

exit 0;

Usage

  • have Perl on your path
  • copy the above perl script to ANDROID-SDK/build-tools/v.v.v/dx.pl
  • rename dx in ANDROID-SDK/build-tools/v.v.v/
    Unix: rename dx to dx-orig
    Windows: rename dx.bat to dx-orig.bat
  • add a new replacement dx which calls through:
Windows: dx.bat
@echo off
setlocal
set args=%*
for /f "delims=" %%i in ('perl "%~dp0dx.pl" %args%') do set args=%%i
call "%~dp0dx-orig.bat" %args%
endlocal
Unix: dx
#!/bin/sh
dx-orig `perl dx.pl $@`
TWiStErRob
  • 44,762
  • 26
  • 170
  • 254