Upload
droidcon-berlin
View
22.469
Download
0
Tags:
Embed Size (px)
Citation preview
greenDAO
A look behind the scenes
Droidcon Berlin 2012, Markus Junginger
About me, Follow me
Android developer since 2007
Founder of greenrobot.de, Munich
@green_dao Most updates
@greenrobot_de
Most important updates
+Markus Junginger
+greenrobot
Agenda
What is greenDAO?
– SQLite database
– ORM
– Code generation based on meta model
Background info and „secret“ internals
– Why code generation?
– Performance Tweaks
Problem with DB Development
Database world || Java world
No object orientation
Data access feels quite low levely
A lot of boilerplate code for SQLite
– SQL scripts, e.g.: CREATE TABLE, Queries
– Cursor iterations
– Parameter binding
Common solution: ORM
ORM offers a higher level API
– Read and write objects
– CREATE TABLE done for you
– Expressing Queries
SQLite
Database
Java Object
Java Object
Java Object greenDAO
Example: SQLite vs. greenDAO
String[] columns = { "note", "date_changed" };
String[] idArgs = { String.valueOf(id) };
SQLiteCursor cursor = (SQLiteCursor) db.query("notes", columns,
"_id=?", idArgs, null, null, "note");
try {
if (cursor.getCount() != 1) {
throw new Exception("Unexpected count: " +cursor.getCount());
}
cursor.moveToNext();
String note = cursor.getString(0);
String date = cursor.getString(1);
updateUi(note, date);
} finally {
cursor.close();
}
// greenDAO
Note note = noteDao.load(id);
updateUi(note.getNote(), note.getDate());
greenDAO Overview
Entities & DAOs
Code generation
Open Source:
https://github.com/greenrobot/greenDAO
Apache 2 license: core library
(embedded in your app)
GPL3: generator
(you usually don‘t have changes here)
greenDAO Structure
Generator Project (Plain Java)
Schema-Model • Entities • Properties • Relations • Indexes, …
greenDAO Generator Lib +FreeMarker
Android Project
Sources
greenDAO Core Lib
Generated Sources • Entities • DAOs
greenDAO Code Generation
Code Generation: Meta Model
In generator project
Defines data model
(your schema)
Define with Java
Example: Model for Generator
Schema schema = new Schema(1,
"de.greenrobot.daoexample");
Entity simple = schema.addEntity("Note");
simple.addIdProperty();
simple.addStringProperty("text").notNull();
simple.addDateProperty("date");
new DaoGenerator().generateAll(
"../DaoExample/src-gen", schema);
Example: Generated Entity
public class Note {
private String text;
// ID, date and constructors skipped
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
Code: Insert, Update, Delete
Note note = new Note();
note.setText(“Say hello to world”);
noteDao.insert(note);
Log.d("Dao", “New ID: " + note.getId());
note.setText(“Save the world”);
noteDao.update(note);
noteDao.delete(note);
QueryBuilder
References generated Properties
Java Complier checks
Example: Get all users with first name
“Joe“, and sort by last name List<User> joes = userDao.queryBuilder()
.where(Properties.FirstName.eq("Joe"))
.orderAsc(Properties.LastName)
.list();
Entity relations
Entity type relates to another entity type
Supports to-one and to-many relations
Unidirectional
Bidirectional: requires manual updates
ToOne Example
Entities Customer & Order
An order has one customer
Modelling in the generator project Property customerId = order.addLongProperty(
"customerId").notNull().getProperty();
order.addToOne(customer, customerId);
Resolving in the app Customer customer = order.getCostumer();
ToMany Example
Entities Customer & Order
A customer places many orders
Modelling in the generator project Property customerId = order.addLongProperty(
"customerId").notNull().getProperty();
customer.addToMany(order, customerId);
Resolving in the app List<Order> orders = costumer.getOrderList();
Active Entities
Have (some) persistence methods
– update
– delete
– refresh
greenDAO Design Goals
Maximum Performance
Low resource usage
– Memory consumption
– Library size
Easy-to-use API
Focus on the essentials
Optimized for Android
Save size, keep it the DRY way
Generate code, but as sparly as possible
Example: load method of DAO
AbstractDao class (core library)
– Implements everything expect readEntity
Generated DAO implements readEntity
– Just construct entities from a cursor position
Library size: 59 KByte + some K per DAO
3 Basic Performance Rules
1. Group DB changes into a transaction!
Can be like 500 times faster; still a FAQ
2. Don’t forget database indexes
3. Use prepared statements (precompiled)
Regular Performance Tracking
Different scenarios are tested
Tracked in Excel files
Excel files are pushed to github
Why Code Generation?
Annotation-based solutions: common with
JEE ORMs (Hibernate, JPA)
Parsing of annotations start-up time
Android & annotations:
getting/setting values requires reflection
Reflection quite slow on Android (n. slide)
Code generation to avoid reflection
Reflection Performance
Method Reflection (roughly)
getInt ~ 50 x slower
getString ~ 50 x slower
setInt ~ 400 x slower
setString ~ 150 x slower
Example: 100,000 Operations
(e.g. 10,000 entities with 10 properties)
setInt: 9 ms, reflected 3875ms
Profiling to find hotspots
Use traceview
Enable in code: Debug.
startMethodTracing(
traceName);
See class
PerformanceTest
Reading entities & Constructor
Entities read from the database
Solution 1: Calling setters MyEntity myEntity = new MyEntity();
myEntity.setX(cursor.getString(0));
…
Solution 2: Constructor only MyEntity myEntity = new MyEntity(
cursor.getString(0), …);
Performance gain: 33%
Optimization Candidate: Cursor
Quite some time is spent in Android API android.database.AbstractWindowedCursor
get… Methods are “slow”
@Override
public short getShort(int columnIndex) {
checkPosition();
return mWindow.getShort(mPos, columnIndex);
}
@Override
public int getInt(int columnIndex) {
checkPosition();
return mWindow.getInt(mPos, columnIndex);
}
Custom Cursor implementation
Replacing SQLiteCursor
de.greenrobot.dao.FastCursor
Performance gain: ~30%
Lookup by ID
Identity Scope (≈ Entity Caching)
Mapping ID Entity
HashMap<Long, MyEntity>
Problem: Long object creation
LongSparseArray<MyEntity>
Problem: does not scale
Evaluated several alternatives
LongHashMap & More
Custom de.greenrobot.dao.LongHashMap
+ Locking improvements
+ Minor performance tweaks
Performance gain: from 30% up to 117%
Performance: Entities / Second
Measured on a Nexus S (1 GHz), Android 2.3
Performance comparison
Measured on a Nexus S (1 GHz), Android 2.3
Current Workflow vs. Migration
Works best if you start from scratch
(Start with Entity modeling)
Migration: additional effort required
– Pre-existing entities: have to be replaced
– Existing tables: entities have to modeled
Ideas how to address migration
– Generic DAO (Annotation based entities!)
– Import existing Model from SQLite DB files
Current Feature Requests
Generate Adapters, CRUD Apps,
Parceable, conversion to JSON/XML, …
Convenience support for async ops
Client/Server(Cloud) data synchronization
More flexible primary keys (PKs)
Pre- and post persist callbacks
What is most important to you?
Disclaimer, Rechtliches
Alle Inhalte urheberrechtlich geschützt.
© Copyright 2011 Markus Junginger
All rights reserved.
Kontakt: [email protected]
http://greenrobot.de
http://twitter.com/#!/greenrobot_de