-
Notifications
You must be signed in to change notification settings - Fork 167
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
Speed-up calls to Realm.Manage #857
Conversation
1c8532f
to
8aec775
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks very good, aside from a couple of things noted.
It seems to me that it would be very cheap for us to always compare scalar fields against their default value, and it shouldn't be much effort to add this check. Can you extend this PR with that?
@@ -25,6 +27,34 @@ internal class DynamicRealmObjectHelper : IRealmObjectHelper | |||
{ | |||
internal static readonly DynamicRealmObjectHelper Instance = new DynamicRealmObjectHelper(); | |||
|
|||
public void CopyToRealm(RealmObject instance) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Objects whose helper is DynamicRealmObjectHelper
cannot exist in an unmanaged state - they always belong to a realm. I think it's safe to make this method throw an exception instead.
*foreach* list woven property in casted's schema | ||
var list = casted.field; | ||
casted.field = null; | ||
((ICopyValuesFrom)casted.Property).CopyValuesFrom(list); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should get rid of ICopyValuesFrom
instead of making it public. Let's add a public AddRange(IEnumerable<T>)
to RealmList<T>
and call that instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That will clash with our desire to make RealmList<T>
internal (#853), so which one do we want more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want both :-) Do you think it will be too much for this PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, you're right. How about we weave the foreach
cycling in CopyToRealm
which would call IList<T>.Add(T)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was a bit of a pain, but I got rid of ICopyValuesFrom
😤 I'll leave internalizing RealmList
to #858.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice!!
I figured it's better to split it in two, so that we can brag about "major speed improvements to Manage" in our release notes. Then after a release or two, we could add the default check and brag about speed improvements again 😆 If we make it ultra-fast in one go, people will think we're not improving anymore! |
Oh haha, fair point. We can save some performance improvements for the next release. |
@@ -85,5 +82,90 @@ public void RealmObject_WhenStandalone_ShouldHaveDefaultEqualsImplementation() | |||
|
|||
Assert.DoesNotThrow(() => _person.Equals(otherPerson)); | |||
} | |||
|
|||
[Test] | |||
public void RealmObject_WhenManaged_ShouldNotThrow() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is fine but I would also like a test in WeaverTests as well that verifies that the expected get
and set
methods are invoked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, I will take a look at the WeaverTests infrastructures and try to come up with one.
*foreach* list woven property in casted's schema | ||
var list = casted.field; | ||
casted.field = null; | ||
((ICopyValuesFrom)casted.Property).CopyValuesFrom(list); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want both :-) Do you think it will be too much for this PR?
Ping @fealebenpae, @kristiandupont care to take a second look? |
@@ -810,6 +809,83 @@ private static bool IsRealmList(PropertyDefinition property) | |||
return property.PropertyType.Name == "RealmList`1" && property.PropertyType.Namespace == "Realms"; | |||
} | |||
|
|||
private static bool IsDateTimeOffset(PropertyDefinition property) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know we've been using strings already, but would it be nicer to create something like
private static bool Is<T>(PropertyDefinition property)
{
return property.PropertyType.Name == typeof(T).Name && ...
}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes it would, but I didn't want to diverge too much from the coding style. Also, when we add StyleCop, we'll probably have to reorder/reformat the whole file and it'll complain about constants/nameof/typeof :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It bugs me that we do string comparison in the first place - I'd much rather we compare TypeDefinition
instances.
I believe that you should remove the |
|
We could get rid of 👍 from me. |
👍 from me as well. Very nice work! |
This is a change that aims two things
Realm.Manage
closer toRealm.CreateObject
AddOrUpdate
(Update object by PrimaryKey #808)The essence here is weaving
CopyToRealm
inIRealmObjectHelper
implementors that replaces the reflection that we used before. Here's the performance comparison29311523Times are in
ms
and the test was performed with100000
objects.Sparse
refers to objects with a lot of properties, where only a few are set.Dense
refers to objects where all properties are set.The current implementation guards against hitting ObjectStore by doing
only for value types, objects, and lists. It doesn't support nullable value types because the IL is getting out of hand as is and didn't seem like it would add a lot of value.