Introduction
to Buck
Francis Toth
DroidCon - MTL 2015
State of the Art
Tools available so far
Ant
. Former build system from Google
. Poor module support
. Very slow
Tools available so far
Maven
. Really ???
Tools available so far
Gradle
. Official build system from Google
. Faster than ANT
. Mediocre module support
. Very slow when many libraries involved
Don't scale :(
Tools available so far
We need a tool which :
. is flexible and easy to configure
. supports modules
. is fast (build & deployment)
. is well integrated with nowadays
IDE's
Typical Android Build
Typical Android Build
An APK is composed of :
. a resources.arsc (xml layouts, drawables, assets...)
. a classes.dex (java code, native code, libraries...)
. some other stuff (manifest, certificates...)
Dependency graph
res
res
lib
lib
src
lib
res
res
R.java
lib
lib
lib
dx
ANT build steps
APK
(generate classes.dex)
APK
src
resources.arsc
dx
Typical Android Build
Typical Android Build
native libraries
classes.dex
resources.arsc
APK
bootstrap
APK
c
c
c
Phone
c
APK
APK
ADB
(5-6 MB/sc)
Typical Android build
Lack of speed :
. APK Packaging takes time
> 7 seconds for large apps
. APK sent through ADB ( 5-6 MB /sc )
. Package Manager does a lot of work
(depending on size & target env.)
Sources : Michael Bolin & David Reiss - Droidcon NYC 2014
Buck
Buck in a nutshell
. Inspired by Google Blaze
. Open-Sourced since April 2013
. Provides fast incremental builds
. Makes a heavy use of parallelization
. Used by FB to build its native apps
. Encourages small and reusables modules organized
around BUCK files
Buck in a nutshell
. A module is defined with a BUCK file
. Declarative/imperative configuration
. Decompose the build process into "Build Rules"
. A build rule is a procedure for producing 1 or 0 output file
from a set of input file
android_library(
name='ui',
srcs=glob(['src/main/java/**/*.java']),
deps=[
'//res/com/droidcon/montreal:res',
'//java/src/com/droidcon/common:common',
'//third-party/guave:guava',
],
visibility=['PUBLIC'],
)
android_resource
android_resource(
name = 'res1',
package = 'com.droidcon.montreal',
res = 'res/droidcon/montreal',
deps = [
'//res/com/droidcon:res',
],
)
int anim fade_in_seq 0x7f04000b
int attr actionBarSize 0x7f0100af
int color fbui_bg_dark 0x7f060071
R.txt
res
deps
An xml-change that leaves the index unaffected won't trigger a regeneration of R.txt.
android_library
android_library(
name = 'lib1',
srcs = glob(['*.java']),
deps = [
'//java/com/droidcon/lib2:src',
'//res/com/droidcon/montreal:montreal-res',
],
)
R.txt
R.txt
R.txt
R.java
deps
src
jar
(without R.java)
Implementation changes do not trigger dependents rebuild.
(merged)
classpath
android_binary
android_binary(
name = 'droidcon-montreal',
manifest = 'AndroidManifest.xml',
deps = [
'//java/com/droidcon:montreal',
],
)
res
resources.arsc
dex
res
R.java
dex
dex
APK
The dex merging has been speeded-up from O(N^2) to O(N lg N)
jar
jar
dex merge
(generates classes.dex)
Distributed cache
build rule
output file
Cache Key
Continuous Integration
Buck is fast !
. optimized dx
. daemon (buckd)
. heavy use of parallelisation
c
Java code
c
Resources
c
Dexing
c
APK packaging
Source : Michael Bolin & David Reiss - Droidcon NYC 2014
Wait ! There's more !
native libraries
classes.dex
resources.arsc
APK
Why my build is slow ?
bootstrap
APK
c
c
c
Phone
c
APK
APK
- ADB Protocol
- Package Manager
These steps must be minimized to increase efficiency
- APKBuilder
Slow build reasons :
the 64K limit
Google Play Services
Guava
AppCompat V7
Android Support V4
Jackson
Joda-Time
Apache Commons Lang3
Apache Commons IO
Gson
Name
Version
Overall Method Count
6.1.11
18.0
21.0.0
21.0.0
2.4.3
2.5
3.3.2
2.4
2.3
29,460
14,842
12,324
8,078
6,731
5,025
3,582
1,571
1,243
Source : https://www.contentful.com/blog/2014/10/30/android-and-the-dex-64k-methods-limit/
native libraries
classes.dex
resources.arsc
Multi-dexed app
Exopackage
bootstrap
APK
c
c
c
Phone
c
APK
APK
- APK Builder only needed for
- Package Manager limited for
- Reduce deployment time
Pros :
res. & native code changes
Java changes only
Thanks to the 64K limit, multidexing is possible
Exopackage
android_binary(
name = 'antennapod',
manifest = 'AndroidManifest.xml',
target = 'Google Inc.:Google APIs:19',
keystore = ':debug_keystore',
use_split_dex = True,
exopackage_modes = ['secondary_dex'],
primary_dex_patterns = [
'^de/danoeh/antennapod/AppShell^',
'^de/danoeh/antennapod/BuildConfig^',
'^com/droidcon/buck/android/support/exopackage/',
],
deps = [
':application-lib',
':main-lib',
],
)
The app entry point has to be changed, along with its configuration.
In production, all those tweaks are disabled, and the APK expects to contain everything in order to run properly.
AntennaPod + Exopackage
Source : https://facebook.github.io/buck/article/exopackage.html
Buck in brief
. Fast, modular and stable
. Drastically reduces build and deployment time
. Migration from Gradle to Buck is (very) easy
. Good support and promising
. Some limits however
Sources
Buck repo :
. https://facebook.github.io/buck/
Discussion group:
. https://groups.google.com/forum/#!forum/buck-build
Buck's documentation
. https://github.com/facebook/buck
Extra thanks for David Reiss, Michael Bolin & Simon Stewart
Text
c
Text
I am a Scala developer at 1Science, but also a mobile dev freelancer.
francistoth@coding-hipster.com
Thank you ! Questions ?
RDD
Partition
Partition
Partition
Cluster
HadoopRDD
FilteredRDD
MappedRDD
HadoopRDD
FilteredRDD
MappedRDD
ShuffledRDD
textfile(...)
.filter(...)
.map(...)
.count()
textfile(...).filter(...).map(...).count()
Worker 1
Worker 2
Worker N
Driver
Worker 1
Worker 2
Worker N
Driver
collect()
}
{
Worker 1
Worker 2
Worker N
Driver
Worker 1
Worker 2
Worker N
Driver
HadoopRDD
MappedRDD
MappedRDD
ShuffledRDD
textfile
flatMap
map
reduceByKey
filter
MappedRDD
Stage 1
Stage 2
Stage 1
HadoopRDD
flatMap
map
reduceByKey
filter
textfile(hdfs://...)
.flatMap(_.split(" "))
.map((_ , 1))
.reduceByKey(_ + _)
.filter(_ > 1)
HadoopRDD
flatMap
map
reduceByKey
filter
textfile(hdfs://...)
.flatMap(_.split(" "))
.map((_ , 1))
.reduceByKey(_ + _)
.filter(_ > 1)
Stage 1
Stage 2
HadoopRDD
flatMap
map
reduceByKey
filter
textfile(hdfs://...)
.flatMap(_.split(" "))
.map((_ , 1))
.reduceByKey(_ + _)
.filter(_ > 1)
(a, 1)
(b, 1)
(b, 1)
(a, 1)
(b, 1)
(a, 1)
(b, 1)
(b, 1)
(a, 1)
(b, 1)
(b, 1)
(a, 1)
(b, 2)
(a, 1)
(b, 1)
(a, 1)
(b, 1)
(a, 1)
(b, 1)
(b, 1)
(a, 3)
Shuffle
}
{
(a, 1)
(b, 2)
(b, 5)
(a, 1)
(b, 1)
(b, 1)
(a, 1)
(b, 1)
(a, 1)
(b, 1)
(b, 1)
(a, 1)
(b, 2)
(c, 1)
(b, 1)
(c, 1)
(c, 4)
(a, 1)
(b, 3)
(c, 6)
Provinces / Territories
People in Canada
Quebec
New Brunswick
British Colombia
Provinces / Territories
People in Canada
People in Canada
People in Canada
People in Canada
People in World
All data from both RDDs
Final joined output
People in Canada
People in World
Final joined output
{ Filter people from Canada }
Driver
Executor
Cache
Executor
Cache
Executor
Cache
Cluster Manager
Driver
Executor
Cache
Executor
Cache
Executor
Cache
Driver
S3
Dataframe
{ JSON }
and more...
Dataframe
{ JSON }
Dataframe
Dataframe
Dataframe
{ Schema }
Dataframe
Rows
+
SQL
Confoo 2016 - Francis Toth
Spark
batches of input data
Spark Streaming
Receivers
input of data streams
results published to external systems
Source : Learning Spark by Andy Konwinski, Holden Karau, and Patrick Wendell
Streaming
Title Text
Copy of Introduction to Buck
By tothfrancis
Copy of Introduction to Buck
- 77