Show HN: Realm (YC S11), a mobile database
realm.io
realm.io
The short version is that most apps tend to do a query on click, fetch from an API and then cache the results in memory. The Realm version fetches from the API asynchronously in the back, pre-fetching results and writing them form the DB on one thread and reading & displaying them on the map from another. This has a few benefits (& drawbacks). On one hand, you do hit your servers a bit more often at first, and you may actually get so much data in the map that the UI component will start to lag. On the plus side, your data points are cached so you can do a lot less API queries over time (especially for something like Foursquare where users tend to stay in the same area and the dataset of venues doesn’t change that often). You also get better control as a designer or developer, and you can trim down & display relevant datasets on the fly.
To sum up, I’d say the key difference is the availability of a local, concurrent data structure that can easily be updated & read from multiple places (i.e. in a few lines of code if you look at the samples on http://realm.io)
One question - CoreData works really well with built in UIViewControllers like TableViewControllers. Any chance you'll be releasing some code that makes wiring up changes in the models to the controls that are displaying that data?
[0] https://github.com/realm/realm-cocoa/tree/master/examples/swift/RealmSwiftTableViewExample
[1] https://github.com/realm/realm-cocoa/tree/master/examples/objc/RealmTableViewExampleIn Realm the object you see is a direct representation of the underlying data, it does not have to copy in all the properties. When you access them, it is the property directly from the db you are getting, not a copy stored in the object. This means that it takes up a fraction of the memory space, and it also means that queries and similar operations can work on the objects directly in the db, without having to instantiate them in objective-c. This means that you can easily scan over millions of objects, without causing a single "fault".
When manually traversing objects you still have to instantiate them, but since they don't have to copy any data, it is a far more lightweight process than faulting.
[0] http://realm.us5.list-manage1.com/subscribe?u=2aab5198c2f56b...
As good as Realm looks for iOS, I think it might be needed more in Android as there are no really viable alternatives other than using sql lite directly.
EDIT: I just came across the REST API / JSON import section in the documentation - really cool stuff!!
The transactions interact with the runloop, so that you are always in an up-to-date read transaction (which always give you a consistent view and never blocks, even when other threads modify the same data). To write, you have to do explicit write transactions.
So your data is always live, consistent and up-to-date without you having to do any explicit coordination (apart from the write transaction on changes) and notifications allow you to always keep your UI up-to-date with the latest changes.
I like that it is multi-platform, but SQLLite is a pretty mature DB store available on all the major platforms anyway. I get that it is faster... but presumably there are there trade-offs for this speed gain. I would like a better understanding of what they are. Transaction support?
(PS: I would also much prefer if your objects can be typed in a way so they are plain, rather than forced inheritance from RLMObject)
EDIT: The blog post at http://realm.io/news/introducing-realm/ answers some of these questions.
The big problems we try to solve are really ease of use & performance. We heard from many developers dissatisfied with the current options on mobile, and the relative complexity to accomplish tasks like accessing data across threads, JSON handling, performance on graph queries, etc. — which the reactions on Twitter seem to confirm. We’ll write a lot more about the tradeoffs in coming weeks, but we’ve really grabbed a lot of perf cycles just by taking advantage of modern techniques such as zero-copy architectures, bitpacking and vectorization. Of course the big implicit tradeoff is that you give up a bit of the relational paradigm in exchange for that speed, although we do maintain ACID transactions, immediate disk persistence by default and schemas.
Completely hear you on wanting plain objects — I personally feel that way too! Unfortunately, there’s no way to achieve what we do without making you inherit from RLMObject, although we do try to make those behave as close as possible to NSObject.
It's extra work, but it lets me manipulate Realm into doing what I want it to do to store data which doesn't conform to an explicit schema. (e.g. a Venue which has an array of address strings, where I don't want the headache of iterating through venue.address[i].string values:
(note: this doesn't look pretty, its doing some funky formatting!)
"venue" : { "name":"Test Venue", "address" : [ "address line 1", "address line 2", "address line 3 for rare instances" ] }
@interface Venue : RLMObject @property NSString name; @property NSData addressData; @end
@interface Venue (AddressToData) @property NSArray address; @end
+ (NSDictionary )defaultPropertyValues { return @{ @"addressData":[NSJSONSerialization dataWithJSONObject:@[] options:0 error:nil] }; }
- (NSArray) address { NSArray address = nil;
if (self.addressData) {
address = [NSJSONSerialization JSONObjectWithData:self.addressData options:0 error:nil];
} else {
address = @[];
}
return address;
}- (void) setAddress:(NSArray )address { if (!address) { address = @[]; }
NSData *data = [NSJSONSerialization dataWithJSONObject:address options:0 error:nil];
self.addressData = data;
} RLMRealm *realm = [RLMRealm defaultRealm];
[realm beginWriteTransaction];
for (NSDictionary *v in json[@"venues"]) {
Venue *venue = [Venue createInDefaultRealmWithObject:v];
NSArray *address = v[@"address"];
venue.address = address;
}
[realm commitWriteTransaction];In early testing we got a lot of higher-level questions about what Realm was exactly, so we decided to go for a descriptive tagline instead, but you’re right that we should add more details about how we compare to Core Data!
[0]http://realm.io/news/introducing-realm/
[1]http://wbyoung.tumblr.com/post/27851725562/core-data-growing-pains
[2]http://alastairs-place.net/blog/2013/04/17/why-core-data-is-a-bad-idea/
[3]http://inessential.com/2014/06/11/core_data_thoughts_june_2014
(EDITS: formatting)We heard a lot of dissatisfaction from the community as far as Core Data is concerned (including from Apple engineers themselves). I’m also not entirely sure you could ever get Core Data performance to the levels we enjoy, since Core Data cannot be any faster than the SQLite underneath, after all. I do want to say that your feedback on how we present ourselves and the work ahead of us is spot on and much appreciated. Many thanks for speaking up, we will work hard to heed your comments & improve.
My huge, huge, huge problem, on the other hand, is sync. I don't want to get locked into iCloud and the idea of Apple offering multi-platform support is unrealistic.
If you offered this as a cross-platform solution + syncing I'd sign up immediately (it sounds like this might be where you're headed anyway).
http://developer.couchbase.com/mobile/#couchbase-lite
I see a lot of comments here about wanting a CoreData replacement that's better at sync, which is exactly the use case CouchbaseLite is meant to solve.
And it's all closed source.
That said, the "insert" benchmark source for SQLite is a bit disingenuous. It makes a new compiled statement every time it inserts - if you're doing 150,000 inserts, you should definitely be reusing that thing. And on Android, greenDAO (probably others) does this automatically for every insert/update. It's not some edge-casey optimization trick, it's normal SQLite use.
That being said I still find the speed of Realm pretty impressive. And it's hard to gauge real world performance from this test. In my experience the real bottle necks around insert are upsets and establishing maintaining relationships.
For reference here are the benchmarks without reusing sqlite statements.
Macbook Pro - Realm: 0.780414 sqlite: 0.464804 FMDB: 0.654659
iPhone 5S - Realm: 2.235381 sqlite: 2.786381 FMDB: 3.336679
And with statement reuse Macbook Pro - Realm: 0.766406 sqlite: 0.189747 FMDB: 0.683823
iPhone 5S - Realm: 2.214847 sqlite: 0.991864 FMDB: 2.832800
Interesting side note: FMDB seems to be spending just as much time finding the cached statement as sqlite takes to prepare a new one. I didn't expect that. I haven't dug into it at all, but I wouldn't be surprised if this due to the fact that the insert statement is relatively simple.EDIT: Just fixed up formatting for the results
Have you set up a pull request / issue by any chance? It paints Realm in a bit worse of a light, but hopefully they'll merge it in and update the site.
I'll definitely watch with interest! I'd love a safe, faster, easier data store than SQLite. I'm certain such a thing is possible, and it would address a massive range of uses. Good luck though - SQLite is pretty fantastic, it's a tough competitor to have :)
Just a side note: The SO link you have in the footer seems to not have any questions about your actual product in the tag, but about Java realms instead.
I’m drafting something to dive deeper into the video now; anything in particular you’d like us to dive into?
There are some benchmarks in our intro blogpost[0]. So I can recommend reading that for a bit more background information. We will have more blog posts coming out soon about the technical details.
It is not part of the initial launch as we want to nail down the local api's with the community first, but look out for announcements soon.
We are not ready to into details about how our sync solution will work yet, but watch out for some announcements soon.
As for the tradeoff, I guess that heavily depends on the specifics of your app. You are the only one who can judge that depending on your current app pain points, maturity and future needs.
This could work elsewhere too? Be usable in python?
On the minus side, We don’t work from everywhere yet, but we have internal bindings for Python, Ruby, C#, Java, PHP and a few other languages. We focused on the iOS launch so far, but we do plan to wrap up those additional implementations and share them on GitHub.
We learnt a lot about Swift introspection and interacting with Swift objects from the Objective-C runtime. We'll share our findings in some upcoming blog posts, so stay tuned!
[0]: https://github.com/realm/realm-cocoa/pull/549 [1]: http://realm.io/docs [2]: https://github.com/realm/realm-cocoa/tree/master/examples/sw...
A Realm database is just a (compact) file that you can send as you see fit. As most BaaS solutions has their own local storage and API it may not always make sense to integrate, except that you could easily store a small Realm file as a blob in any BaaS and transfer it remotely.
It will also really soon be possible to export some or all objects as json which you then again can send to remote services. That does however take up much more space/bandwidth compared to Realms compact data format, but could be needed if you want to persist remotely in another database format.