Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cesarvr/mixed implementation #3501

Merged
merged 23 commits into from
Jan 25, 2021
Merged

Cesarvr/mixed implementation #3501

merged 23 commits into from
Jan 25, 2021

Conversation

cesarvr
Copy link
Contributor

@cesarvr cesarvr commented Jan 13, 2021

What, How & Why?

Mixed Type

It provide integration between the realm::Mixed type into our Realm JS SDK.

Usage

As mentioned before the Mixed type basically allows the user to delegate the type inference at runtime to Realm-JS, so instead of defining the types in the schema like this:

const Schema = {
    name: 'Test',
    properties: {
     a: 'int',
     b: 'string', 
     c: 'bool'
    }
}

Which require the user to remember the types, with the new Mixed type this is not longer necessary because this type deduct the type automatically, you can use the below schema interchangeably with the one above:

const Schema = {
    name: 'Test',
    properties: {
     a: 'mixed',
     b: 'mixed', 
     c: 'mixed'
    }
}

This in combination with Dictionaries can facilitate a more agile way of development where the users are not constrained by initial schema rules or mistakes.

Performance

To make sure we don’t degrade the user experience, we tested the performance by creating two tables with 2 Million rows using a wide variety of types, then we use the fixed schema as the reference for the performance.

Mixed 207 seconds
Schema 175 seconds

We found out that the Mixed type is just 18% slower than the non-Mixed.

Profiling

To understand this slowdown we can take a look at the profiling information:

We expend the majority of CPU time is spend deducting types and parsing complex types as we can see in the figure below:

Screenshot 2021-01-13 at 13 59 09

Another explanation for the performance degradation vs the fixed schema option is the time spent by the CPU dealing with the Mixed type in Realm Core:

Screenshot 2021-01-13 at 14 03 25

Those are the points where we need to focus for further speed improvements.

This closes # RJS-544

☑️ ToDos

  • 📝 Changelog entry
  • 📝 Compatibility label is updated or copied from previous entry
  • 🚦 Tests
  • 📝 Public documentation PR created or is not necessary
  • 💥 Breaking label has been applied or is not necessary

If this PR adds or changes public API's:

  • typescript definitions file is updated
  • jsdoc files updated
  • Chrome debug API is updated if API is available on React Native

@cesarvr cesarvr requested review from kneth and fronck January 13, 2021 13:18
@bmunkholm
Copy link
Contributor

Just a comment to the motivation. It's not (originally) intended to defer type decisions but to allow storing mixed values when there is a need for that.

@cesarvr
Copy link
Contributor Author

cesarvr commented Jan 13, 2021

Just a comment to the motivation. It's not (originally) intended to defer type decisions but to allow storing mixed values when there is a need for that.

Thanks for the comment @bmunkholm, but I think I used the word inference, instead of defer, meaning that the framework will figure out the type for you.

And of course the side effect of that is that it will store everything you trow at it as long as we support the type.

@bmunkholm
Copy link
Contributor

This in combination with Dictionaries can facilitate a more agile way of development where the users are not constrained by initial schema rules or mistakes.

It doesn't have any effect to the feature itself (that's all good), I'm merely pointing out that above is not really the motivation for this feature or how we will promote the use of it. It shouldn't make you "lazy" or defer decisions about your data types you want.

@cesarvr cesarvr mentioned this pull request Jan 16, 2021
23 tasks
@@ -0,0 +1,37 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2016 Realm Inc.
Copy link

@fronck fronck Jan 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] *2021 ;)

src/js_mixed.hpp Outdated

#pragma once

#include <common/type_deduction.hpp>
Copy link

@fronck fronck Jan 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[question] Would you not need the #if REALM_PLATFORM_NODE guard here as well?

src/js_mixed.hpp Outdated
};

template <typename Context, typename Value, typename Utils>
class HandleString : public MixedWrapper<Context, Value> {
Copy link

@fronck fronck Jan 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[code style] I think these classes would be better named Mixed* (e.g., MixedString) rather than Handle*. Just to make it clear that they deal with Mixed values only.
Alternatively, wrapping them in a mixed namespace or, even better, nested as classes within `MixedWrapper.

@nirinchev
Copy link
Member

Another note on the description of the PR: you can't use those two schemas interchangeably because:

  1. You'll need a migration for a local Realm.
  2. That'll be a destructive change for a synchronized Realm which is not allowed.

src/js_mixed.hpp Outdated
template <typename Context, typename Value, typename Utils>
class HandleBinary : public MixedWrapper<Context, Value> {
Mixed wrap(Context context, Value const &value) {
auto owned_binary_data = Utils::to_binary(context, value);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BinaryData and StringData are very similar in Core - they don't hold a reference to their contents. So it's surprising that you need the cache for the string case, but not in the binary case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, thanks for the heads up 👍

Mixed wrap(Context context, Value const &value) {
auto date = Utils::to_date(context, value);

double milliseconds = Utils::to_number(context, date);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[q] Isn't it better to std::move the date (and the ts at the end) variables here?

src/js_mixed.hpp Outdated
Comment on lines 165 to 169
if (strategy == nullptr) {
throw std::runtime_error(
"The " + TypeDeduction::realm_typeof(mixed.get_type()) +
" value is not supported for the mixed type.");
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is hit, it would be a bug in the SDK, wouldn't it? There should be no type in Mixed that can't be wrapped to Value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good observation, but even in that unlikely case it would be nice to fail gracefully.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we did want to fail gracefully, I would suggest rewording the error message to something that makes it clear to the developer that this is a bug on our end and they should file a ticket.

Comment on lines 75 to 77
if (value.IsUndefined()) {
return type_TypedLink;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is undefined returned as typedlink?

Comment on lines 88 to 90
if (value.IsObject()) {
return type_Link;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be TypedLink?

return type_Link;
}

return type_Link;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a weird default - perhaps hitting this should be an error or return type_Invalid?

Copy link

@fronck fronck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few nitpicks about the explicitness of the Mixed handler types, and a possible memory leak we need to look at.

Also, some tests are needed.

Otherwise, good work.

@cesarvr cesarvr requested a review from steffenagger January 21, 2021 13:46
@cesarvr cesarvr merged commit 960ce9f into develop Jan 25, 2021
@cesarvr cesarvr deleted the cesarvr/mixed_implementation branch January 25, 2021 09:59
kneth added a commit that referenced this pull request Mar 10, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 16, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants