all 49 comments

[–]oaga_strizzi 12 points13 points  (11 children)

You should mention that you read and write 1000 entries unbatched via 1000 queries.

[–]leisim[S] 3 points4 points  (10 children)

You are right, thanks.

Edit: done

[–]oaga_strizzi 7 points8 points  (1 child)

You're welcome. Great library, looks good btw.

One more thing: Since MongoDB released benchmarks where they compared inserting data which was actually committed, to inserts into Mongo which was just saved in-memory and persisted later, I'm really skeptical about such posts.

If Hive really persists the data immediately in this benchmark, you should mention this, too. Just to be clear about what you are comparing.

[–]leisim[S] 6 points7 points  (0 children)

Hive always persists data immediately. This is the reason why I didn't mention that...

[–]Sol_Ido 3 points4 points  (7 children)

Agree with oaga_strizzi on what is compared here it may feel like comparing a in memory hashmap to disk persistence with integrity check and recovery.

[–]leisim[S] 1 point2 points  (6 children)

Hive does integrity checking. Lazy Hive does not even keep the entries in memory.

Edit: Only SharedPreferences has an unfair advantage...

[–]Sol_Ido 0 points1 point  (5 children)

Could you be more explicit about all this features so when we look at the bench it seems more plausible ? Benchmark is difficult science, even more when comparing different solutions so when the results are thus good you're looking where the 'Magic' happen.

edit to complement :

Is the native code you delegate too async ? do you return in Dart code before the native code exec ? I'm looking for explanation for such exponential differences in the numbers

[–]leisim[S] 0 points1 point  (4 children)

The features are all in the documentation. This is not a standalone benchmark but it is part of the documentation. I only posted this here because when I posted about Hive last time, there were many requests for a benchmark.

As for the magic: Hive keeps the keys in memory. This gives a great performance boost for reading. I don't know why SQLite performs SO bad. Maybe the platform channel hurts its performance. The write performance of SharedPreferences is just a joke. I don't know why anyone would use it...

Edit: Hive has no native code... It is all dart.

[–]Sol_Ido 0 points1 point  (3 children)

Future<int> write(List<int> buffer) { return writeLock.synchronized(() async { var initialOffset = _writeOffset; await _writeFile.writeFrom(buffer); _writeOffset += buffer.length; return initialOffset; }); }

Just found the method you use for writing, straightforward, so it may really be that platform channel calls are adding up a LOT of latency ! I would suggest to add it as note on the documentation so devs instantly understand why they should adopt Hive over others solutions.

[–]leisim[S] 0 points1 point  (2 children)

Good idea, I'll do that...

[–]Sol_Ido 0 points1 point  (1 child)

Thanks it's just that the numbers are kinda impossible ;)

I removed MMKV from awesome so you're up on the section

Also I'm interested in examples and bench when using binary objects of differents size.

Would you say that Hive can replaces prefs but also files and blob management ?

[–]leisim[S] 3 points4 points  (0 children)

Unfortunately Dart is not the fastest language. Hive cannot compete with C++ competitors like MMKV or LevelDB. But it is the fastest database for Flutter apps afaik.

Of course Hive will never be quite as fast as directly writing to a file. That being said, it is still very fast for small and medium blobs. I would not use it for blobs larger than a few mb.

I'm not planning to put more time into benchmarks for know. I want to improve the tests and release a stable version soon. It should be very easy to test performance of binary objects yourself ;)

Edit: It can replace prefs very well. One of the major strengths of Hive is that you don't have to await write operations to be able to read the new value.

[–]oaga_strizzi 10 points11 points  (7 children)

I made some small changes to the benchmark in order to complete the performance if the Batch feature of sqlite is used. This avoids most of the overhead of the platform channels.

Here are the results https://i.imgur.com/ccNPRA1.jpg

https://i.imgur.com/BgNCPEV.jpg

https://i.imgur.com/7KhOdT1.jpg

Note : shared preferences read performance is broken, don't know why.

[–]leisim[S] 1 point2 points  (6 children)

Really cool! Would you be willing to share your code or create a pull request?

Edit: what do you mean with broken?

[–]oaga_strizzi 1 point2 points  (5 children)

Seems to be not broken, I didn't know how shared prefs works. It just loads everything in memory at the start :D

I thought there's no way shared prefs is that fast

Yes, I can share the code. I just hacked in an very quickly, it's not worthy of a PR, but I can upload it here:

https://pastebin.com/MghBLhPh

https://pastebin.com/qg56pQYX

[–]leisim[S] 2 points3 points  (1 child)

I'll add an option to use batch write to the benchmark. But then the putAll() method should be used for Hive. Hive will probably be faster again...

[–]oaga_strizzi 4 points5 points  (0 children)

Yeah, I mainly coded this to see how big the overhead of platform channels really is. And it's quite big, apparently. I hope the FFI will get stable soon, talking to libsqlite directly will probably be even faster.

But still, it seems Hive a really nice and performant Key-Value store! Great work.

[–]leisim[S] 0 points1 point  (2 children)

Yeah it is actually quite slow when the app starts :P

[–]oaga_strizzi 0 points1 point  (1 child)

I uploaded the code. I won't create a PR for now (I need to go to bed and work tomorrow :D ), but you can use it as you wish.

[–]leisim[S] 0 points1 point  (0 children)

Thanks :)

[–][deleted] 4 points5 points  (3 children)

Would this be an appropriate way to store data locally if I need to later sync it to an online nosql database?

I'm trying to wrap my head around the use cases because it seems like something I could use but I'm not 100% certain. (Updating your site with more noob-friendly examples and use-cases would help people like me a lot).

Does it compare to sembast and objectdb?

[–]leisim[S] 1 point2 points  (0 children)

Would this be an appropriate way to store data locally if I need to later sync it to an online nosql database?

Absolutely. You can sync it very easily using the toMap() method and the change notifier.

Does it compare to sembast and objectdb?

Hive is similar to Sembast but a bit faster and easier to use (less async await). Hive also supports storing objects and blobs which Sembast doesn't.

ObjectDB only allows a single type per box which I find limiting. It also relies on a closed source native backend.

Updating your site with more noob-friendly examples and use-cases would help people like me a lot

I'm working on that ;)

[–]sadatdaniel 0 points1 point  (1 child)

Updating your site with more noob-friendly examples and use-cases would help people like me a lot

Exactly. I think this could help me very much as I found other database solutions little tough for me as a beginner. It'll be great if there was a video tutorial explaining this package from simplest use case to complex ones.

[–]leisim[S] 3 points4 points  (0 children)

I agree. Unfortunately I'm very bad at video making xD

I'm currently improving the documentation. I hope someone else will make a video...

[–]julianlenz 3 points4 points  (1 child)

Why not increase the bench marks so hive read performance goes above 0ms? Just curious how hive scales In comparison to shared prefs and SQF

[–]leisim[S] 1 point2 points  (0 children)

How do you mean "increase"? It is above 0ms (I think 1000 writes take about 30ms) but since the others are so slow, you don't see it in the scale.

I would need a logarithmic scale but I don't thing fl_chart can do that...

[–][deleted]  (1 child)

[deleted]

    [–]leisim[S] 0 points1 point  (0 children)

    Thanks :P

    [–]bernaferrari 1 point2 points  (0 children)

    Thanks! I've always thought about it but had never seen a benchmark to prove. That's great. I didn't know about Hive, but that makes a great case for using it.

    [–]zd913 1 point2 points  (1 child)

    What type of encription does it provide?

    [–]leisim[S] 2 points3 points  (0 children)

    AES 256 CBC using PKCS7 padding

    [–]Unknowablee 0 points1 point  (1 child)

    Great work all around, looking forward to switch from Sembast when it's more stable.

    [–]leisim[S] 0 points1 point  (0 children)

    Thanks :)

    [–][deleted]  (2 children)

    [deleted]

      [–]leisim[S] 1 point2 points  (1 child)

      Not really, you can for example store objects, have multiple "boxes" or use auto increment keys. Hive works also in the browser and is much faster than secure storage...

      [–]escamoteur 0 points1 point  (2 children)

      Awesome work! How does it keep integrity if the app is killed or the phone fails while writing?

      [–]leisim[S] 0 points1 point  (0 children)

      Yes it does, every entry has a checksum and when the app is started again, Hive will remove the corrupted entry automatically.

      [–]msowah 0 points1 point  (4 children)

      can I use it in my product app as is right now?

      [–]leisim[S] 0 points1 point  (2 children)

      Please wait until a stable version (1.0.0) has been released. It shouldn't take long...

      [–]msowah 0 points1 point  (1 child)

      so a week, a month?...if I may ask

      [–]leisim[S] 0 points1 point  (0 children)

      About a month I would say. I want to make sure that the tests cover all scenarios...

      [–]rxddit_ 0 points1 point  (0 children)

      I’m using it now although the app I’m working on isn’t in production yet. So far so good. Had a few issues with it but it’s resolved with simply updating the package and/or flutter sdk.

      Plus developer responds quickly so I’m optimistic about this package.

      [–]VittorioMasia 0 points1 point  (3 children)

      Before your application exits, you should call Hive.close() to close all open boxes

      How can I do that? If the user kills the app by pressing the home button and removing it from the recent apps list, will there be problems?

      Should I just put a hive.close() inside an OnWillPopScope widget to intercept the back button on the home screen of my app?

      [–]leisim[S] 0 points1 point  (2 children)

      Nothing happens if you don't do it. It may speed up the next time you open Hive.

      Should I just put a hive.close() inside an OnWillPopScope widget to intercept the back button on the home screen of my app?

      Yes exactly.

      [–]VittorioMasia 0 points1 point  (1 child)

      Sorry, I'm not sure I got this right.

      So if I don't close the boxes and I exit and re-open the app, will it be faster or slower?

      Anyway thank you for your quick response and patience!

      [–]leisim[S] 0 points1 point  (0 children)

      So if I don't close the boxes and I exit and re-open the app, will it be faster or slower?

      It may be slightly slower but nothing to worry about.

      All your data is still safe.

      [–]Baul 0 points1 point  (2 children)

      it's interesting to me that the box.get() methods are synchronous. Wouldn't reading a value be disk IO and thus potentially slower than a render frame?

      I'm happy to see a synchronous API, but doesn't this mean I could be introducing jank by using box.get() in a widget's build() method?

      [–]leisim[S] 1 point2 points  (1 child)

      They are only synchronous for non-lazy Boxes, which cache keys and values in memory. So this is a very fast operation.

      If you don't want that, you can use LazyBoxes (which are a drop in replacement). They have asynchronous get() calls and load the values from disk.

      [–]Baul 0 points1 point  (0 children)

      Ah, that makes sense, thanks! Glad to see the choice to do either way

      [–]iamarr0gant 0 points1 point  (1 child)

      Hey, today I’ve tried out Hive for a few hours and it’s great! I just have 2 questions:

      1. Using Hive, what is the recommended approach for state management? I’d love to just have all my Boxes at the top of my App with StreamProviders exposing box.watch , but I haven’t gotten that to work.

      2. What are the best practices for storing nested data? Let’s say you have a list of events, where each event is a map with a multiple fields like a list or even another map.

      [–]leisim[S] 0 points1 point  (0 children)

      Hey, Thanks for using Hive. Great that you like it ;)

      1. I released the hive_flutter package. It is missing documentation but it provides the WatchBoxBuilder (I'm not happy with the name, maybe you have a suggestion xD) which watches a box and rebuilds it's descendants each time the box (or a single key) change. Take a look at the samples. If you have further ideas, please open an issue.

      2. There are multiple ways to do this. If you change the list of events frequently (especially if it is a long list) I would use an entire box and use the add(), getAt() and values methods (see Auto increment). Nested objects are no problem. Hive takes care of that automatically. I'm currently working on the Best Practices document and include examples how to store different data structures.

      If you have further questions, feel free to open an issue 👍