Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • 02:59
    glennawatson review_requested #292
  • Oct 17 19:29
    dnfclas commented #292
  • Oct 17 19:27
    dnfclas commented #292
  • Oct 17 19:27
    lexisstv opened #292
  • Oct 17 07:49
    lock[bot] locked #243
  • Oct 16 01:49
    lock[bot] locked #254
  • Oct 15 18:04

    RolandPheasant on UniqueChangeSet

    (compare)

  • Oct 14 18:49
    lock[bot] locked #253
  • Oct 13 13:22
  • Oct 13 07:49
    lock[bot] locked #252
  • Oct 13 06:48
    lock[bot] locked #251
  • Oct 13 06:48
    lock[bot] labeled #251
  • Oct 12 09:34

    reactiveuibot on 6.13.18

    (compare)

  • Oct 12 09:22

    glennawatson on master

    Fix tests that looks like Asser… (compare)

  • Oct 12 09:22
    glennawatson closed #291
  • Oct 12 08:59
    chuuddo opened #291
  • Oct 11 04:36

    reactiveuibot on 6.13.15

    (compare)

  • Oct 11 04:36

    reactiveuibot on 6.13.16

    (compare)

  • Oct 11 04:35

    reactiveuibot on 6.13.17

    (compare)

Gitter
@ReactiveGitter
[gdurand, Reactive, Inc.] What is strange is that the Parent property never changes: I just add the Domains to the flat cache. And the Children view is properly updated even without the AutoRefresh. So AutoRefresh does something more, even though there is no actual property notification after the Domain is added.
[gdurand, Reactive, Inc.] ok
[glennawatson, Reactive, Inc.] then just before your AsObsevableCache go back to the main thread?
[gdurand, Reactive, Inc.] BTW I am running this as a unit test (xUnit), if it has some special thread behaviour...
Gitter
@ReactiveGitter
[gdurand, Reactive, Inc.] Not too sure I did the right thing: Connect().ObserveOn(Scheduler.Default), and then .ObserveOn(Scheduler.CurrentThread).AsObservableCache()
[gdurand, Reactive, Inc.] In any case, no improvement, and actually, Connect().ObserveOn(Scheduler.Default) slows down the process, even without AutoRefresh
Gitter
@ReactiveGitter
[roland, Reactive, Inc.] @gdurand can you post your code a simplified snippet including the domain objects? I ask this because there are specialisations in DD for flattening nested collections and they may apply to your use case
[roland, Reactive, Inc.] Also have you looked at the snippets project as there are examples of autorefresh and examples to flatten a nested collection.
Gitter
@ReactiveGitter

[gdurand, Reactive, Inc.] [Fact]
public void Test()
{
var source = new SourceCache<MyDomain, int>(_ => _.Id);

for \(int i = 0; i < 1000; i++\)
{
    source.AddOrUpdate\(new MyDomain\(source, null\)\);
}

}

private class MyDomain : AbstractNotifyPropertyChanged
{
public int Id { get; set; }

public MyDomain Parent { get; set; }

public MyDomain\(SourceCache<MyDomain, int> source, MyDomain parent\)
{
    Parent = parent;
    source.Connect\(\).AutoRefresh\(\_ => \_.Parent\)
        .Filter\(\_ => \_.Parent != null && \_.Parent == this\).AsObservableCache\(\);
}

}

[gdurand, Reactive, Inc.] The time of execution is exponential: 5s with 600 objects, 19s with 1000, and always less than 1s without AutoRefresh
[gdurand, Reactive, Inc.] I actually receive the list flattened from the server, so I don't try to flatten a tree.
Gitter
@ReactiveGitter
[gdurand, Reactive, Inc.] If I encapsulate the for loop inside source.Edit, the result is the same, so I guess the overhead comes from creating the support for autorefresh (probably registering event handlers for each existing domain)
[gdurand, Reactive, Inc.] I so, I don't think I'll be able to use autorefresh this way. I'll have to use AutoRefreshOnObservable somehow
Gitter
@ReactiveGitter
[roland, Reactive, Inc.] Use .AddOrUpadate(myenumerable) rather than adding one at the time. This will work wonders for performance
[gdurand, Reactive, Inc.] my implementation is a bit more complex than that. This was a unit where I wanted to test performance
Gitter
@ReactiveGitter
[gdurand, Reactive, Inc.] but I think I found a good solution with AutoRefreshOnObservable (at least the overhead is much more reasonable). I setup a subject and call OnNext when Parent changes.
[gdurand, Reactive, Inc.] BTW, including the for loop inside Edit is twice slower than without. I didn't expect that.
[roland, Reactive, Inc.] I do not understand why you are creating a filtered clone of the parent. Each time you do, you are creating a copy of the original and then applying a filter. This will always be extremely slow.
[roland, Reactive, Inc.] Previously I have created caches with nested children with tens of thousands of child caches and I made it fast (although not necessarily at first attempt)
Gitter
@ReactiveGitter
[roland, Reactive, Inc.] It would probably be better to maintain the parent cache separately with raw data only and use operators to apply transforms, groups or filters as these operators are well optimised. However I do not understand your problem enough to suggest a best solution
Gitter
@ReactiveGitter
[roland, Reactive, Inc.] If you have the time to create a project and (put it on GitHub) which simulates your requirement I will help make it fast.
Gitter
@ReactiveGitter
[roland, Reactive, Inc.] Also being as you receive the data in flat form (I just noticed that comment), I suggest a) maintain the flat data inside a cache b) group on the data as this much quicker than lots of filters c) regarding autorefresh, this only ever needs to be applied in one place only, depending where will depend on what event triggers the autorefresh
Gitter
@ReactiveGitter
[gdurand, Reactive, Inc.] My setup is very simple: I have a root object (Project) that stores a flat cache of Domains, and each Domain can have a parent domain and child domains. I want each Domain to expose its Children as an observable cache and this cache should be updated when a Domain has its Parent changed.
[gdurand, Reactive, Inc.] Here is a test project with my naive AutoRefresh implementation: https://github.com/gdurand/dynamicdatatests.git
Gitter
@ReactiveGitter

[glennawatson, Reactive, Inc.] in your example

for (int j = 0; j < nbChildren; j++)
                {
                    project.Domains.AddOrUpdate(new Domain(project, (i + 1) * nbChildren + j, parent));
                }

can become

project.Domains.AddOrUpdate(Enumerable.Range(0, nbChildren).Select(i => new Domain(project, (i + 1) * nbChildren + j, parent)));

Which makes 210 add notifications to 20

[glennawatson, Reactive, Inc.] not sure if that helps with your end domain issue since you may have simplified to demonstrate
Gitter
@ReactiveGitter
[roland, Reactive, Inc.] @gdurand can you give me permission to push straight to the example? Would make it very easy to collaborate
[roland, Reactive, Inc.] scrap that. I see you already have done so
Gitter
@ReactiveGitter
[gdurand, Reactive, Inc.] @glennawatson this loop is just used for the test. And anyway, if I add all the domains to a list and then AddOrUpdate this list, the time to process is still the same
[glennawatson, Reactive, Inc.] how so, each one of those generates a source change observable, while with the ienumerable version it causes a aggregated observable change etc
[gdurand, Reactive, Inc.] I think the problem is related to the creation of 1 autorefresh per domain that will listen to all the domains already present. In the end I get n domain observing n domains
[glennawatson, Reactive, Inc.] I agree that’s also a issue, but don’t discount the IEnumerable vs single add
[gdurand, Reactive, Inc.] as I said I tested with the enumerable, with only 1 addorupdate, and there is no change (at least the Autorefresh problem hides it very well)
Gitter
@ReactiveGitter
[gdurand, Reactive, Inc.] I'm not sure the AutoRefresh is optimized in relation to the number of AddOrUpdate (at least it's not what I observe)
[glennawatson, Reactive, Inc.] I’m guessing Roland can confirm, it will just cause one regeneration of items vs n of the for loop
[glennawatson, Reactive, Inc.] that’s what I seen
[glennawatson, Reactive, Inc.] but thats more if you add the items after generating the AutoRefresh()
[gdurand, Reactive, Inc.] that's what I do: the Children observable is created in the constructor of a Domain, so it is indeed added to the main cache after the generation
Gitter
@ReactiveGitter
[roland, Reactive, Inc.] Where does project data come from and whether does domain data come from? Are they sources as 2 distinct data sources? And is the code taking the 2 sources and creating a one to many relationship?
[gdurand, Reactive, Inc.] There is only one source: IEnumerable<Domain> ProjectService.GetDomains(). And the cache should be updated from the returned value, once normally.
Gitter
@ReactiveGitter
[gdurand, Reactive, Inc.] I pushed more tests, where I compare AutoRefresh(propertyAccessor) and AutoRefreshOnObservable(one global observable that never emits) and, quite surprisingly, the latter is waaaay slower than the former, though AutoRefresh actually uses AutoRefreshOnObservable
[gdurand, Reactive, Inc.] and to answer your question more completely Project and the domains come from 2 sources
[roland, Reactive, Inc.] The reason for slowness is excessive amounts of change set notifications coupled with repeated auto refresh subscriptions (auto refresh are opt in for a reason). That was clear cut as soon as I saw the problem. What my questions are geared up to is to try and understand your data and your problem so I can suggest a simple solution - the always is with rx / dd / linq
[roland, Reactive, Inc.] ...any way I am working now and will sign back in later
Gitter
@ReactiveGitter
[gdurand, Reactive, Inc.] OK, I made it work quite simply: I do not use AutoRefreshOnObservable but I pass my global Observable of Parent changes as a parameter to Filter. All I wanted to do was actually reapply the filter, but I thought AutoRefresh did just that
[gdurand, Reactive, Inc.] I had to use a Filter overload that didn't quite suit my needs though: to pass a reapplyFilter I had to use the Filter with an observable predicateChanged. I would have preferred using the static filter
[gdurand, Reactive, Inc.] Also I think I found a bug on the Filter overload with only the reapplyFilter parameter: it call DynamicFilter with a null predicateChanged, which causes it to throw a ArgumentNullException
[gdurand, Reactive, Inc.] I will file an issue on github
Gitter
@ReactiveGitter

[unknown]
[RolandPheasant/DynamicData] Issue created by gdurand
RolandPheasant/DynamicData#128
Filter(reapplyFilter) calls the DynamicFilter constructor with a null predicateChanges, which causes it to throw an ArgumentNullException.

Also I don't understand the usage of this method: there is no filter specified.

Gitter
@ReactiveGitter
[unknown]
[RolandPheasant/DynamicData] Issue created by gdurand
RolandPheasant/DynamicData#129
Currently you cannot refresh a cache filtered with a static predicate.
An overload Filter(Func<TObject, bool> filter, IObservable<Unit> reapplyFilter) could be useful.