GregoryConrad / mimir

⚡ Supercharged Flutter/Dart Database
https://pub.dev/packages/mimir
MIT License
119 stars 8 forks source link

Cannot allocate memory (os error 12) #227

Open siddharthadevops opened 1 year ago

siddharthadevops commented 1 year ago

The exception occurs on an iPhone 7 Plus device, iOS 15.7.7

FfiException(RESULT_ERROR, Cannot allocate memory (os error 12), null) flutter: #0 FlutterRustBridgeBase._transformRust2DartMessage (package:flutter_rust_bridge/src/basic.dart:129:9) flutter: #1 FlutterRustBridgeBase.executeNormal. (package:flutter_rust_bridge/src/basic.dart:70:9) flutter: flutter: #2 MimirInterface.getInstance (package:mimir/src/interface.dart:44:5) flutter:

In an iPhone 14 pro max, it happens when creating a second index.

GregoryConrad commented 1 year ago

Wow, that is really annoying. Can't believe I didn't across that in testing. Thanks for reporting this, along with the info!

I'll need to do some tests to be sure, but I'm guessing that is related to iOS' mmap implementation, which is really dumb from what I gathered, due to iOS limiting address space.

I can attempt to put out a fix for the iPhone 7 sometime soon hopefully to at least get mimir to work on that device, but you definitely won't be able to open 2 indexes on iOS devices for the immediate future. When #101 gets fixed, this issue will also get fixed. However, don't expect that anytime soon because it's quite a large code change in a dependency, and will also require Dart native assets (which are still in the works).

In the meantime, use 1 "combined" mimir index but add a field to your documents that specifies the actual index to use. Then you can query and add documents using that one particular field so that you can still have logical indexes, despite not truly having physical indexes. This does come with the limitation that you must use one shared primary key for both, but you can concat the index name with the actual primary key to get around that limitation for now as well. Like:

const docs = [
  {'id': 'indexA-001', 'index': 'indexA', 'contents': 'bla bla bla'},
  {'id': 'indexB-123', 'index': 'indexB', 'foo': 'bar'},
];
// Now you can search/filter/add documents using the `index` field.
siddharthadevops commented 1 year ago

Thanks for the quick reply. I was unaware of the problem with memory addressing in iOS. I've never programmed for iOS in native, just a little dabbling with notification extension 😅 Having only one index is not a problem at all, since, as you say, you can set as many filters as you like. It would be interesting to clarify this issue in the package documentation. This package looks promising. If it works fine, I think it will soon be a Flutter favorite.

GregoryConrad commented 1 year ago

@siddharthadevops I don't have an iPhone 7 Plus handy, so I might ask you to help me do some testing here to figure out the sweet spot to fix the iPhone 7 compatibility problem (it's not an exact science unfortunately). I'll put out a new dev release tomorrow at some point and I'd appreciate it if you could try it out on that device. Might take a few pings back and forth to get it working.

An aside: this issue is really unfortunate because there isn't anything I can really do to fix it, except for switching away from LMDB and to redb for the backing store over in meilisearch/heed, which is a huge amount of work

siddharthadevops commented 1 year ago

I'll try it as soon as it's available. Relying on LMDB can be a significant limitation for Apps that need to index large amounts of information. Especially in developing countries where most of the devices are medium/low range. But, I understand that replacing it is a huge job. So for now, let's try launching the library on an iPhone 7 🙂

GregoryConrad commented 1 year ago

Well it's not that LMDB is bad for indexing large amounts of data or that it's bad for low end devices--it actually is less problematic on Android than it is on Apple's range of products. It's just that it uses some systems level features that Apple's sandboxes disallow, or in this case, have really poor support for. Thus, the solution is to switch away from a rather complicated dependency like LMDB and to something written fully in Rust with minimal dependencies, like redb, which doesn't face the same limitations. It comes at a slight performance hit, but that actually should be negligible for mimir since its performance bottleneck is elsewhere.

In any case, @siddharthadevops the new dev release should be out in less than an hour.

GregoryConrad commented 1 year ago

It looks like melos (my monorepo tool) messed up the release version number slightly. In any case, here is a link to the release (you will have to specify this exact version, including the -dev bit, in your pubspec.yaml): https://pub.dev/packages/mimir/versions/0.0.1-dev.0+1

siddharthadevops commented 1 year ago

... flutter_mimir: 0.0.1-dev.0+1

Same exception:

flutter: FfiException(RESULT_ERROR, Cannot allocate memory (os error 12), null) flutter: #0 FlutterRustBridgeBase._transformRust2DartMessage (package:flutter_rust_bridge/src/basic.dart:129:9) flutter: #1 FlutterRustBridgeBase.executeNormal. (package:flutter_rust_bridge/src/basic.dart:70:9) flutter: flutter: #2 MimirInterface.getInstance (package:mimir/src/interface.dart:44:5) flutter:

GregoryConrad commented 1 year ago

Hmm, every time I try to fix this I'm actually just limiting the maximum db size. Might try once or twice more, but if I need to make changes beyond that, I might be inclined to just bump up the minimum supported iOS version to prevent the db from being too small on other devices

GregoryConrad commented 1 year ago

Also, just to check, when you added flutter_mimir: 0.0.1-dev.0+1 to your pubspec.yaml, did you do it like:

flutter_mimir: 0.0.1-dev.0+1

or:

flutter_mimir: ^0.0.1-dev.0+1

(the first is correct, the ^ notation may give you the wrong version here)

siddharthadevops commented 1 year ago

The first one. flutter_mimir: 0.0.1-dev.0+1

The device has iOS 15.7.7

would it be possible to set a parameter with the size of the database?

siddharthadevops commented 1 year ago

On the simulated iPhone 8, running iOS 16.4, it works fine

GregoryConrad commented 1 year ago

@siddharthadevops When you get a chance, please try 0.0.2-dev.1!

would it be possible to set a parameter with the size of the database?

Perhaps with some refactoring. I think I'd rather set it via the Rust side with some sort of operating system checking crate if I were to go down that path.

siddharthadevops commented 1 year ago

Still not working with:

flutter_mimir: 0.0.2-dev.1

flutter: EXCEPTION: FfiException(RESULT_ERROR, Cannot allocate memory (os error 12), null) flutter: #0 FlutterRustBridgeBase._transformRust2DartMessage (package:flutter_rust_bridge/src/basic.dart:129:9) flutter: #1 FlutterRustBridgeBase.executeNormal. (package:flutter_rust_bridge/src/basic.dart:70:9) flutter: flutter: #2 MimirInterface.getInstance (package:mimir/src/interface.dart:44:5)

GregoryConrad commented 1 year ago

Thanks, and sorry about the delay here. Have been working on a few different projects

I'll try to get a new release out tomorrow that uses exp. backoff to find a good mmap size that picks the best possible size based on the device. Really wish I didn't need workarounds like that but not much I can do until mimir switches over to the redb backend

GregoryConrad commented 1 year ago

Should have a new release out, 0.0.2-dev.2, in a couple hours. @siddharthadevops I'm going to have to ask for you test it out again haha

If this one works you may be able to get away with opening multiple indexes on iOS, but indexes opened after the first will likely have a decreased maximum size.

siddharthadevops commented 1 year ago

Good news here!

It works perfectly. When I have some time, I will try to add more on iOS.

Many Thanks!

GregoryConrad commented 1 year ago

Fantastic! Thanks for all of your help in testing out the releases.

I'll release 0.0.2 to partially fix this issue at some point today

sarp86 commented 7 months ago

@siddharthadevops on iOS 17.2.1 we get error 12. Unfortunately the App crashs. We think is memory issue. We dont find solution to solve this problem.

We also have different search tabs (events, movies,…) and we search in all tabs at same time. The app may also crash because it searches in several tabs at the same time (and does not close them first and open new).

Is there a solution for this?

GregoryConrad commented 7 months ago

@sarp86 I don't remember this issue causing apps to crash, but if the issue is in fact from mimir, you can use this workaround to avoid the issue.

If your app is crashing, it is likely there is an issue somewhere else.