ObjectBox Swift 1.0 is here! Since the first public alpha released 10 months ago, we’ve worked hard and made major changes to put Swift first, tune the performance, and iterate on the API. We hope you will love the result.
All of this, to bring you the features you expect from a database, but more importantly – the features that we think delight developers and sets ObjectBox apart from other databases out there. Let’s swiftly (cheap pun intended) dive into ObjectBox Swift 1.0:
Built with Swift in Mind
// objectbox: entity
ObjectBox isn’t just a database bolted onto Swift. Your database entities are regular Swift classes or structs that you devise. No need to subclass a particular class (as with CoreData’s NSManagedObject), nor to write tedious serialization code. 😊
All you need to do is add one property for the unique ID, build your project, and ObjectBox’s code generator will write a little bit of code for you, just like the Swift compiler does for Codable objects. All that’s left then, is to call a simple method like put() on the object to write it out:
We’ve tried to keep this simplicity throughout the Swift binding, e.g. making it very easy to use any RawRepresentable enum without writing any conversion code.
Automatic Schema Migrations
A common chore with databases is schema migration. ObjectBox takes care of that. If you add a new property or class there are no additional migration steps required. Old objects will keep working, and new objects will be saved with the additional fields. Similarly, adding new classes will add them to the database without any error-prone migration steps.
Moreover, you do not need to maintain a dedicated schema, because your classes and structs are the schema in the first place.
To ensure ObjectBox knows how to save object references, you use a wrapper class. Either ToOne or ToMany, instead of a straight reference or an array. This lets ObjectBox lazily load the related objects from the database, only when you’re actually accessing a related object.
The Swift 1.0 release brings you our complete set of relations: One-to-many, many-to-many, and their corresponding back-links. ToMany behaves just like any other Swift collection, you can add or remove objects as you please with your familiar methods like append().
let results=tryquery.find()// All Authors matching query.
// All last names of the matching authors:
Of course ObjectBox lets you perform queries to collect data; either complete objects or individual properties (basic Swift data types).
But with ObjectBox you don’t mess around with query strings or unpack data from cursors. You simply write Swift expressions with function calls and operators you’re already used to.
Also, you get to keep the type-safety guarantees and compile-time checking. So you don’t have to spend hours figuring out why your query doesn’t return the proper results, just to discover you made a typo in a field name in a query string.
ObjectBox lets you then operate on these objects, watch a query for changes, retrieve the results, delete the objects matching a query etc. The source code even contains a file that adds Combine support so you can integrate with its pipelines to take advantage of Apple’s newest technology.
As always, we would love to hear your feedback! Do you like ObjectBox as much as we do? We put our hearts in this product and are excited to learn your thoughts: What features are you most excited about, what are we missing?
We haven’t written much about a topic very dear to us: performance. We will cover this in a follow up post. Also, look forward to our ObjectBox Swift 1.0 benchmarks, which we will release soon including the sources.
Today, over 90 percent of enterprise data is sent to the cloud. In the next years, this number will drop to just 25 percent according to Gartner. Where is the rest of the data going? It’s not going anywhere. It is being stored and used locally, on the device it was created on. This is edge computing.
Mist, fog, edge, cloud – the terms ☁️
To bring some light into the terminology mess: The terms “mist” and “cloud” constitute the ends of a continuum.
Mist covers the computing area that takes place on really tiny, distributed, and outspread devices, e.g. humidity or temperature sensors. To make it a bit more tangible: These devices generally are too small to run an operating system locally. They just generate data and send it to the network.
As opposed to this, the cloud refers to huge centralized data centers.
The underlying megatrend enabling this shift is cheaper and more efficient hardware, as well as the emergence of edge databases. Edge databases are specifically designed to run on the edge and therefore lean and efficient. Both the number of mobile and IoT devices, and alongside data volumes are exploding at exponential rates. At the same time computing capabilities on the edge level are advancing faster than those on the cloud level. So, the edge has increasingly more power – power that is currently often underused.
New applications and requirements drive the shift to the edge:
Offline Capability is necessary in some applications, but many offer it for a more seamless user experience (think about it: When you are mobile, at some point you will be offline)
Advantages of setting your project up in the cloud ☁️
So, what about the cloud; do we still need it in this era of Edge Computing? Setting up your project in the cloud has some advantages: First of all, the setup itself is comparably easy, as the cloud servers are managed by another organization. This also means that you do not need to worry about scalability of your servers or data loss, i.e. the need for redundancy, reducing overall downtimes. Additionally, cloud systems also are well tested, automatically updated and often encryption mechanisms are provided natively. This eases up on administration. Generally, you can use the cloud rather quickly without worrying about lengthy and error-prone setup tasks. Using servers also centralizes the logic: clients will just call a unified interface (e.g. Web/REST).
A typical IoT-setup would often be centralized and look like this today:
Advantages of running your application on the edge 🗡️
Running an application on the edge, e.g. your Android phone, a Smart Home Server, or in the car, has a couple of advantages:
The application works everywhere, all of the time (offline / online)
Great supersmooth User Experience (UX) as the app can respond in (near) realtime
Data stays where it was produced and belongs, the user maintains data ownership
Cloud / Connectivity costs go way down
Some tangible use cases for edge computing:
Many Mobile Games run on the edge. As a game developer you really want your users to be able to engage with the game whenever they feel like it and have the time. And as a gamer, you may well want to play when offline, for example when commuting on the underground. Also, gamers really care about the user experience with very smooth animations and high-fidelity visuals.
Autonomous driving as well as any human safety application needs to work independent from an Internet connection and in realtime. Imagine crashing because the car was trying to connect to the cloud or still waiting for the database to respond.
Smart home or smart health applications should work even when there is no connection, but moreover: Why should you personal health data leave your private space? You probably would want to own that data and keep it safe in the local environment. That way it is much less likely that s.o. will try to hack your individual data versus millions of centrally stored data.
Predictive maintenance apps usually need to process tons of data or high-fidelity data like video streams. Transferring all this data to the cloud usually means such high cloud costs that the project becomes unprofitable. Therefore, they usually are run on the edge and only aggregated data transferred to a central server.
Unlikely. Often you want some data accessible from anywhere. Synchronizing parts of the data to the cloud (or an on-premise central server) allows you to combine many of the advantages from edge and cloud computing. Thus, the edge is a natural extension of the cloud that makes applications all the more powerful. We believe that future scenarios will often look like this:
This line of reasoning is supported by the fact that all major cloud companies, e.g. Amazon, Google, Microsoft, are pursuing an edge strategy.
Why should Android developers care about Edge Computing? 🚀
Here is why designing your app to run on the edge will help you be successful on the Play Store: There are roughly 2.1 mill. Android Apps to choose from today in the Play Store. To stand a chance in that market you need to delight your users and get good app store ratings. Edge Computing delivers on the app traits users care about most: performance, security, and availability.
Users care about performance – a lot 💨
Whenever an app responds to a query directly instead of taking a round-trip to the cloud and back, it should be faster. More importantly, you can measure and optimize more reliably, as the latency is independent from the network connection. This enables the fast high-quality digital experience consumers want.
Reliable performance was found to be the second most important trait for app users in a study by PacketZoom.
A study by appdynamics found that more than eight out of ten respondents had deleted or uninstalled at least one mobile app because of performance issues.
The same study found that 44% of respondents closed the app when experiencing poor network performance, but even worse: 32% even uninstall the app altogether. They also found, the reverse is true for fast performing and reliable apps with usage increasing.
As an Android developer you also know that many consumers cannot or do not care, why an app is not working. If the application is not working or just responding very slowly, users are dissatisified and annoyed. Therefore, as the developer you need to make sure your app always performs well.
“When your app depends on a network, latency is out of your control.”
Now, you might need to query data from the network. That’s fine; if most of your app is running independent from a connection, there are tons of ways to optimize user experience for connectivity loss and network latency.
Security is a hot topic and can be a USP 🛡️
Users care about security, and this is a trend that will – in the face of the loss of huge amounts of personal data by tech giants – only continue to grow. When you leave data at the edge, on the device of the user, data security is much easier to provide. On top, data ownership is clear, easing up on data privacy.
Data is much more secure stored in one place than when transferred over the network – possibly again and again and again. Android provides a good basis for keeping internally stored data safe. If data security and privacy are important for you, your app, or your users, think about keeping data locally and then only synchronizing data you really need accessible from anywhere. Last not least, while an individual phone may be hacked, it is less likely to occur and only an individual dataset is compromised (as opposed to millions of datasets).
Offline first – deliver an always-on-feeling 🔌
Users do not care about connectivity, they simply want to use the application when they want to – at home, in a department store, in a train, on a flight, on vacation. And when they can’t access an app, their user experience is bad. Even today in a highly connected world, there are lots of times where people have no connectivity or need to switch data off to save battery. The app that supports them in these times ;), is the one they will love and use
The most important advantage of doing an offline-first app is the availability of the app. Google translate is a great example of an app that you want to be offline-capable. Chances are that when you need it most you are in a place where you do not have a (affordable) connection. But you might also appreciate being able to read and search through your mails when you are on a plane too. Or type WhatsApp messages that go out when connected again, or just enjoy a round of Subway Surfers.
Offline-first apps make it possible to move content off the server and onto the phone. If an app only has to go to the server when it needs to, rather than all the time, it will be faster and more reliable. This is particularly significant where content doesn’t change often, but users require fast access.
Secondly, for an offline-first architecture you need a local storage as a primary source of data, e.g. a database. Changes to data are made in this layer. Application also can and usually do have networking components to synchronize data to a server. However, this connection to the backend is mainly used in the background to synchronize the local database.
So, why does not everybody do it all the time? Well, there are use cases where it does not make sense to go the extra mile for the limited functionality that edge computing would bring, e.g. in a parking app. Obviously, most relevant data points like your car and the availability of parking spots are changing all the time. So, you really are dependent upon a constant connection, or rather several constant connections: From the spots to the cloud and from the cloud to the app. However, there is another reason: Offline-capable apps are hard. That is why we developed ObjectBox Sync.
Does any app need to run at the edge? ⚖️
As always, there are some cases where the cloud makes perfect sense, indeed is the only option – and the same is true for the edge. You need to assess what you want to achieve and where the value lies for your application and users.
Sustainable Computing: Why the edge is saving the world 🦸
If you do not need to push all the data to the cloud, where large chunks of it might not even be used, you might want to take a step back and consider the broader picture: What do all these billions of mobile and IoT devices (that are quite capable) do while they wait for the cloud to respond? Nothing.
Sending data to the cloud unnecessarily is wasteful in two respects: Use of bandwidth and server capacity (which comes down to infrastructure, electricity and physical space) and the big waste of underused resources.
We’ve been optimizing ObjectBox for speed right from the beginning, making it the fastest database for edge computing around. However, the fastest library in the world is useless if its interface to your language isn’t optimized for that language’s strengths and weaknesses. The 0.8.0 release of ObjectBox for Swift gives you a nearly 70% performance boost out of the box by improving the way we integrate with Swift:
How did we Achieve this Speed-Up?
When we created ObjectBox’s Swift binding, we did not have our C API yet. So, to bridge between the C++ database core and Swift, we implemented a number of classes using Objective-C++. Objective-C++ is neat: it looks to Swift like Objective-C (so like a Swift class), but will happily call into C++ code.
Objective-C is also a very different language from Swift, and particularly generics and structs don’t have a direct equivalent in Objective-C. So when we realized that many reactive frameworks in Swift were built around structs, we decided to change gears. We rewrote a number of core Objective-C classes in the Swift binding as Swift classes on top of the C API that we now use in all our newer language bindings, eliminating a lot of Objective-C’s dynamic dispatch, and generally improving upon algorithms here and there.
The main goal was to give our users struct support and lay the groundwork for taking advantage of Swift 5.1’s upcoming UTF8 strings by eliminating use of the UTF16-based NSString. We also wanted to bring ObjectBox’s Objective-C-beholden error handling in line with Swift conventions. So we expected modest speed-ups here and there, but a speed increase this noticeable even before Swift 5.1 was a pleasant surprise, and we wanted to get these improvements into our users’ hands as quickly as possible.
Using structs with ObjectBox
One rather unique aspect of Swift compared to other languages is how Swift defines the term struct as value type and class as reference type. That makes structs incredibly handy for cases where you want to guarantee an object can never change.
Thread-safety, for instance: if you know an object is unchangeable, there is no chance of race conditions while editing. You need no locks, no copies; your threads can all safely operate on the same memory.
However, when you put an object into your ObjectBox database, put(_:)updates the object’s id property to establish the association between the database entry and your object in memory. ObjectBox can’t do that with unchangeable structs, so we needed to make a slight adjustment to ObjectBox’s usual simple put(_:) flow:
let myUser=User(id:0,name:"Kathryn Drennan",admin:true)
Missed the difference? It’s tiny: You use put(struct:) instead of the regular put(_:). put(struct:) will create a copy of the struct you gave it with the ID changed to whatever ID the object was assigned in the database (the copy is what we store in savedUser in the above example).
So, what if you want to make changes? The way you change immutable structs is to make a copy with the one thing you wanted to change set to a different value. So while you could save it to the database using put(struct:), you already made a copy of the object, and it will not change after being saved, because it already has an ID. Won’t that second copy be wasteful?
That’s why Box now also offers putImmutable(_:). If you know that your object has already been saved, and you don’t need a copy. Just call putImmutable(_:). instead of put(struct:).
// assert(myUser.id == savedUserID)
This will return the ID for your convenience, but you can always ignore it, if you do not need it.
What else has changed?
While we’re always improving things under the hood, not much should change for your existing ObjectBox code. Apart from the new ObjectBoxError enum replacing the janky old Objective-C-style OBXError... classes, your existing code should just compile. All the changes are in the generated code.
Today, we are bringing the power of ObjectBox to Go. Whatever solution you are building, be it a web service, an IoT/IIoT solution, or any data-driven application, you will benefit from the efficiency and speed of ObjectBox (see benchmarks below). Let us know what you think!
Let’s look at some code, and see how ObjectBox persists Go structs (objects):
The ObjectBox Go API allows you to create data-driven cross-platform apps. ObjectBox supports x64 and 32 bit ARM (ARMv6 and ARMv7) CPUs, enabling you to benefit from a super-fast scalable database on IoT devices, industrial edge gateways or, for example, the Raspberry Pi family (from the minimalistic Pi Zero to the high-spec Pi 3B+). At the same time, you can now target desktop and server apps running on Linux, MacOS, or Windows using Go.
How to get started
To get started, please have a look at the ObjectBox Go docs. Here’s the TL;DR version for your bash:
go install github.com/objectbox/objectbox-go/cmd/objectbox-gogen/
go test github.com/objectbox/objectbox-go/...
This will clone the repository to your GOPATH, download the objectbox-c library and install the ObjectBox code generator.
At this point you can start using ObjectBox in your project – just define a struct you want to persist, add //go:generate objectbox-gogen comment in the same file and run go generate ./… on your project. See Getting started for more details.
We have done some quick CRUD performance tests to give you an impression about the speed ObjectBox provides. On a i7-8850H CPU, ObjectBox consistently processes over 1.5 million CRUD operations per second with 4.4 million object reads per second:
To put these numbers into perspective, we also did a comparison using an edge computing platform and two leading NoSQL databases. We won’t spill the names and final numbers just yet, as we are going to release all the details very soon. 😉
Disclaimer: ObjectBox was the only database running in embedded mode, which is not supported by the others in this setup. Obviously this can have a significant impact on performance. On the other hand, this is the most resource friendly mode of operation (RAM and CPU), which might be very relevant if you target restricted ARM32 devices.
This is the first public version of ObjectBox for Go and we are more than excited to get your feedback on it. We have prepared a short questionnaire for you, which should only take 1-2 minutes. Your feedback is extremely valuable to make ObjectBox a fun tool to use.
While this initial release covers all basic features, the native core of ObjectBox offers much more than what is currently exposed to Go. For example, a complete set of query conditions and relations between objects. Also, we will introduce a client/server operation mode. This will allow ObjectBox to run in Containers (e.g. Docker) and in classic server setups. As a major theme, the ObjectBox team is also working on data synchronization across devices. This keeps edge devices and gateways “in-sync”. Sync also enables seamless integration with mobile apps (Android and iOS) pushing relevant data to mobile clients and back. Of course sync will also be available for Go. You can sign up here for updates on sync.
Two days ago, we attended the Swift Lighting Talks Meetup in Munich for the very first time. We had beer, pizza and listened to Sebastian Sellmeier’s presentation on making programming accessible and Denis Grebennicov’s presentation on the process of developing a Document Scanner app. It was fun and very instructive, thanks!
We also gave a 15 minute sneak peek talk about our ObjectBox iOS binding. Markus covered the basics of ObjectBox before sharing how we managed to overcome iOS constraints in our APIs. Finally, he disclosed the first (early) performance benchmarks on iOS, which we think are quite encouraging…
Do you know our new super fast mobile database ObjectBox yet? With versions 0.9.9 and the just released 0.9.10, ObjectBox made great progress to stabilize features for the 1.0 release. With an increasing number of apps using ObjectBox, we were able to spot and fix some less obvious issues. We believe that ObjectBox 0.9.10 is the most stable release ever. If you did not dare to check out the beta version yet: now is a good time to have a closer look.