1. Nulayer launch night 2011!!

    November 30, 2011 by peterkieltyka comments

    It’s hard to believe that in 2008 we were just two guys in an office the size of a broom closet in Liberty Village. Today, two offices later (but still in the village), we are a team of more than 20 creators filled with passion and big dreams.

    Since we launched Crowdreel in 2009, we’ve been flying under the radar, putting our hearts and souls into two products I couldn’t be more proud to say we made. Our best work ever: Pressly and ScoreMobile.

    They are the culmination of a year’s worth of hard work by the Nulayer team. Well done everyone!

    Thank you to Score Media and the Toronto Star for believing and trusting our team in the midst of many unknowns. Innovation is a leap of faith.

    This leads us to November 24th, the day ScoreMobile app for iPhone hit the stores. Since the day we launched, we’ve already topped 400k users, and now sitting at #1 in Canada and #2 in US for Sports! Crazy. We have lots more planned and can’t wait to continue to innovate with the good people at The Score.

    The Toronto Star’s web app, the first ever tablet experience powered by Pressly, launched a few days earlier on November 14th. So far, the most amazing result to surface is the proof we are making a difference in the way people read on the Web. Without giving up too much info, The Star increased user engagement by well over 10x. And users on all devices, from PlayBook to iPad, have been tweeting and emailing us with glowing reviews. People love the reading experience – its working!

    The Star was the first step in our vision to revolutionize the way people read and discover content. As a Toronto based company, we couldn’t be more proud than to have taken that step with a great Canadian publisher.

    This is just the beginning, we’re going to light it up in 2012.

    Thank you to all of our friends, family and colleagues who celebrated these two major achievements with us at our Launch Night party. The next day, we roll into the office around 11am (pretty good), and Will says to me “Pete, we gotta launch more products so we can throw more parties!” …  Agreed! That’s the plan.

    Also, thank you to Esther Kim for planning the party, it was a hit! And thanks to Janick Laurent for the beautiful photography.

    Cheers!


  2. Introducing NULevelDB for iOS

    November 14, 2011 by nulayer-brent comments

    NULevelDB is an Objective-C API for Google’s leveldb key-value database. NULevelDB hides leveldb’s C++ interface while maintaining its functionality, using semantics and patterns which are more suited to Objective-C and more standard in Cocoa and iOS software.

    We created a new Objective-C database API in response to performance issues with Core Data. Core Data is a powerful framework with a lot of incredible features. But those features do not always come for free, and they can create bottlenecks. And we didn’t need them. We needed a key-value database.

    Alternatives

    After evaluating a number of embeddable database solutions, leveldb looked like the best alternative. Other solutions that we considered include:

    • CouchDB is a document-oriented database sever. It’s not a pure key-value store. It lacks an Objective-C binding. CouchDB embedded still runs like a server: the database exposes a socket-based protocol interface on a dedicated thread, not a direct API. In addition, it’s quite large.

    • Berkeley DB, or “db” for short, has been around for a long time. A version of it even ships as part of iOS, but the API is inscrutable to those of us since spoiled by object-oriented design. Documentation is sorely lacking.

    • Vanilla SQLite is easy to use on its own, but, as with Core Data, it is designed to solve different kinds of problems.

    We looked at other options, too, but either they weren’t mature enough, lacked Objective-C or at least C-friendly bindings, or had incompatible licenses.

    leveldb

    Although very new, leveldb is quite mature. It is reliable, fast, and powerful, and the API is clean and intuitive. It features concurrency support, built-in compression, and tight memory use. The fact that it’s written in C++ was only a minor impediment. Writing an Objective-C wrapper felt quite natural, even for someone with very little C++ experience.

    The documentation and headers are your best guide, but here’s a quick overview.

    You open a database with one function call, DB::Open(), passing a file path and options. This returns a status by value, and a new, opaque database object by reference.

    Once you have a database, read, write and delete to your heart’s content. Put() take a key and a value, and adds an entry. Get()) take a key and returns a value. Delete() take a key and removes an entry. Keys and values are represented by a Slices: simple wrappers around data buffers. For efficiency, slices don’t copy data. Don’t delete their referenced data while the slice is still alive.

    Besides basic operations, you can explore the database with the Iterator class. Ask the target database to create an Iterator on your behalf. Then use the Iterator to seek or step through keys sequentially. The sequence follows the sort order.

    Sort order is determined by the Comparator class. You can make your own comparator, or use the default. Use it to find your boundary condition while iterating. Once you specify a comparator to go with a database, don’t change to another one—correct sorting and search of entries in the database requires that the comparison algorithm be consistent.

    When you are finished with your database, delete it normally. But first, make sure you free any Iterators you have created, or it will crash.

    leveldb has a a few more features, but they aren’t used by NULevelDB yet.

    Getting NULevelDB

    NULevelDB is available as source code from github.

    The source includes an Xcode 3 project which builds an iOS universal static framework called NULevelDB. (For more about universal static frameworks for iOS, please see the iOS Universal Framework Template on github.)

    The framework target depends on another target that builds leveldb as a static library. There is a third target for running a small set of unit tests.

    To make the framework available to your application, build it and copy the built product to your application project directory, adding it to your application target at the same time. IN addition, you must add the libstdc++ library to your project. Also, add the -all_load option to your linker flags for all build configurations, or you will get countless C++ linking errors. If you wish, you can include NULevelDB in your project by building the leveldb library and adding the NULDBDB class files to your project directly. (You still need to make the same linking-related modifications to ensure your application builds and runs.)

    Using NULevelDB

    To create a new database from your application, instantiate a new NULDBDB object using the designated initializer:

    http://gist.github.com/1358429

    or just use -init to use the default location and write buffer size.

    The interface for NULevelDB mimics that of leveldb, with some simplifications and some additions. For our uses, defining separate classes for Iterators, Slices, Comparators and the rest has not yet been necessary. (These are areas of future work.) Instead, NULDBDB provides support for a variety of different kinds of keys and values, as well as convenience enumeration methods.

    The simplest approach is to use keys and values that adopt the NSCoding protocol. Internally, NULDBDB converts objects to and from keyed archives and stores them as NSData. Then you only have to work with objects. By adopting NSCoding on your custom classes, they are immediately compatible with the database.

    To add or update an entry:

    http://gist.github.com/1358432

    To retrieve an entry:

    http://gist.github.com/1358440

    To delete an entry:

    http://gist.github.com/1358441

    In addition to reading and writing, you can check whether an entry already exists. In the implementation, this uses an Iterator to search for the provided key. If an Iterator is valid after a seek, it has found the key; otherwise the key does not exist.

    http://gist.github.com/1358446

    In all cases, it’s up to the application to make sure that it knows what kind of object is being stored under any key, or to inspect the value to find out what it is. As is normal with NSCoding, if you use collections, objects held by them must also adopt the NSCoding protocol.

    leveldb will store as much data as you ask it to, quickly and efficiently.

    Faster Access for Common Cases

    For better performance, use one of the streamlined interfaces. These reduce the number of times data needs to be copied. For example, there are methods customized for dealing with string keys and data values.

    There are various enumeration methods, one for each of the API access styles. Most enumeration methods take two keys, for the start and end points, and a block that is called for each key found in the range. If the block returns NO, the method terminates early.

    For example, you may wish to find the biggest object held by a group of keys in a certain range, all of which are prefixed by “MY_KEY:”. But you may wish to end the search early if you find a value bigger than some high water mark.

    http://gist.github.com/1358452

    (Currently, the retain/release semantics are optional, but the enumeration APIs will probably be changed to avoid creating autoreleased objects, to reduce memory spikes while iterating.)

    More Examples

    The distribution includes some test projects for performance measurement. Along with the unit tests, these show the most common ways to use the database.

    I have a fork of SDURLCache on github which uses NULevelDB. SDURLCache is a replacement for NSURLCache, which does not cache on disk in iOS.

    There are some good opportunities for improving and enhancing the code with new functionality. Please fork us! We look forward to your pull requests.


  3. You better watch us (says IDC)

    March 6, 2011 by jeffbrenner comments

    This month, IDC (a renown global think tank on all things digital) named Nulayer as one of 10 Digital Media Companies to Watch in 2011. 

    We’re proud to be listed among Toronto’s brightest up and coming digital media companies. And we’re even happier to be part of this software revolution going on right now, making Toronto a world-class player in the industry.

    The study features ten emerging companies that are innovating and excelling with a variety of new media technology solutions. Read the rest here.

    Thanks IDC and kudos to all the other companies!

    Link: IDC


  4. Ruby ProTip: Better DSL’s

    January 24, 2011 by nickmulder comments

    DSL’s in Ruby are easy to build. What I am about to show you is far from new, but it’s a great trick and its worth the refresher.

    Consider this DSL

    http://gist.github.com/790023

    Now consider this DSL

    http://gist.github.com/790024

    There is one subtle difference, we don’t need the f’s! Here is how to pull it off:

    http://gist.github.com/790027

    You could also support both if you wanted:

    http://gist.github.com/790029

    When building a DSL it’s better not to be wishy-washy. Choose one version and stick to it.

    I prefer the instance_eval version. (Though I will typically use Proc.new to capture the block. More on that later.)

    @nickmulder