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

First steps to reduce operator object layouts #388

Merged
merged 95 commits into from
Apr 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
95 commits
Select commit Hold shift + click to select a range
2235883
First steps to reduce operator object layouts.
bartdesmet Apr 17, 2017
ca2276d
Optimize Aggregate layout.
bartdesmet Apr 17, 2017
e3801c1
Optimize Catch layout.
bartdesmet Apr 17, 2017
71f078a
Optimizing CombineLatest layouts.
bartdesmet Apr 17, 2017
5d7f07d
Reducing usage of LINQ in CombineLatest.
bartdesmet Apr 17, 2017
73d9a3d
Optimizing layout of DefaultIfEmpty.
bartdesmet Apr 17, 2017
3e80686
Optimizing layout of Defer.
bartdesmet Apr 17, 2017
46db24c
Sealing sinks of Materialize and Dematerialize.
bartdesmet Apr 17, 2017
fba2b05
Optimizing layout of Distinct.
bartdesmet Apr 17, 2017
83da56e
Specializing layouts of Do.
bartdesmet Apr 17, 2017
40fdad3
Sealing some sinks.
bartdesmet Apr 17, 2017
ad3ed2d
Optimizing ElementAt layouts.
bartdesmet Apr 17, 2017
8b8ae3f
Optimizing layouts of Min and Max.
bartdesmet Apr 17, 2017
269b2b2
Renaming observers in ForEach.
bartdesmet Apr 17, 2017
608addb
Optimizing layout of Multicast.
bartdesmet Apr 17, 2017
c2da1f0
Optimizing layout of ObserveOn.
bartdesmet Apr 17, 2017
3fe870b
Optimizing layouts of Empty, Return, and Throw.
bartdesmet Apr 17, 2017
45ed06d
Optimizing Zip layouts.
bartdesmet Apr 17, 2017
2559fd5
Refactoring some helper methods.
bartdesmet Apr 17, 2017
053ad76
Optimizing list creation in Zip.
bartdesmet Apr 17, 2017
a4ed268
Removing unused fields.
bartdesmet Apr 18, 2017
381904c
Further optimizations to Zip.
bartdesmet Apr 18, 2017
21b8d55
Optimizing layouts of Skip and Take.
bartdesmet Apr 18, 2017
dbe5c04
Optimizing layout of WithLatestFrom.
bartdesmet Apr 18, 2017
6ce27fc
Sealing some more sinks.
bartdesmet Apr 18, 2017
8936200
Optimizing layout of Finally.
bartdesmet Apr 18, 2017
a015a24
Optimizing layout of TimeInterval.
bartdesmet Apr 18, 2017
ffbfb15
Optimizing layout of Timestamp.
bartdesmet Apr 18, 2017
af34401
Sealing a few more types.
bartdesmet Apr 18, 2017
40b9627
Optimizing layout of ToObservable.
bartdesmet Apr 18, 2017
872838d
Optimizing layouts of SequenceEqual.
bartdesmet Apr 18, 2017
0a237b1
Optimizing layouts of SkipLast.
bartdesmet Apr 18, 2017
fccd480
Optimizing layout of TakeLastBuffer.
bartdesmet Apr 18, 2017
63a92a2
Removing unused field.
bartdesmet Apr 18, 2017
d54c29e
Optimizing layouts of TakeLast.
bartdesmet Apr 18, 2017
d969ef4
Optimizing layouts of SkipWhile
bartdesmet Apr 18, 2017
54bbbb9
Optimizing layouts of TakeWhile
bartdesmet Apr 18, 2017
0ea7f8a
Adding comment to Aggregate.
bartdesmet Apr 18, 2017
7cac0c2
Optimizing layout of Amb.
bartdesmet Apr 18, 2017
d65505d
Optimizing layout of Using.
bartdesmet Apr 18, 2017
42a258c
Optimizing layout of Synchronize.
bartdesmet Apr 18, 2017
6e947bf
Simplifying code in Synchronize.
bartdesmet Apr 18, 2017
466c01b
Optimizing layouts of Timer variants.
bartdesmet Apr 18, 2017
2ccfff8
Optimizing layouts of Timeout.
bartdesmet Apr 18, 2017
05e85e5
Optimizing layouts of Scan.
bartdesmet Apr 18, 2017
48d661a
Optimizing layouts of Sample.
bartdesmet Apr 18, 2017
4794774
Optimizing layout of Case.
bartdesmet Apr 18, 2017
f7be3a0
Adding a comment to Collect.
bartdesmet Apr 18, 2017
971515a
Adding a comment to Contains.
bartdesmet Apr 18, 2017
769038e
Optimizing layout of DelaySubscription.
bartdesmet Apr 18, 2017
ecba902
Adding a few comments.
bartdesmet Apr 18, 2017
a3f6f63
Some improvements to FromEvent[Pattern].
bartdesmet Apr 18, 2017
34ef5d0
Some stylistic fixes to Generate.
bartdesmet Apr 18, 2017
94b8a42
Optimizing layouts of Generate variants.
bartdesmet Apr 18, 2017
384e5f8
Misc. cosmetic changes.
bartdesmet Apr 18, 2017
f944355
Sealing sinks for Join.
bartdesmet Apr 18, 2017
83d6ced
Sealing some more sinks.
bartdesmet Apr 18, 2017
1698aa7
Optimizing layouts of Merge variants.
bartdesmet Apr 18, 2017
fc8e754
Further optimizations to ObserveOn,
bartdesmet Apr 18, 2017
8a3e2fe
Sealing some more sinks.
bartdesmet Apr 18, 2017
7d962de
Optimizing RefCount layout.
bartdesmet Apr 18, 2017
c8cf043
Optimizing layouts of Repeat.
bartdesmet Apr 18, 2017
e92f0e7
Stylistic change to Scan.
bartdesmet Apr 18, 2017
add3eb5
Initial refactoring of SelectMany.
bartdesmet Apr 18, 2017
e83e57f
Optimizing layouts of SkipUntil.
bartdesmet Apr 18, 2017
d341459
Optimizing layouts of TakeUntil.
bartdesmet Apr 18, 2017
6195a07
Sealing sinks for Sum operators.
bartdesmet Apr 18, 2017
c495634
Optimizing layout of Switch.
bartdesmet Apr 18, 2017
6ee70bb
Marking lock field in Synchronize as readonly.
bartdesmet Apr 18, 2017
cee8450
Marking lock field in Switch as readonly.
bartdesmet Apr 18, 2017
808738d
Adding some comments to TakeLast.
bartdesmet Apr 18, 2017
9be1673
Fixing SelectMany operator instantiation.
bartdesmet Apr 18, 2017
ad172aa
Further reducing object layout of SkipWhile.
bartdesmet Apr 18, 2017
5c35ea3
Optimizing layouts of Throttle.
bartdesmet Apr 18, 2017
597061b
Marking a field in ToArray as readonly
bartdesmet Apr 18, 2017
e4de57f
Marking a field in ToList as readonly.
bartdesmet Apr 18, 2017
2dc321e
Optimizing the layout of SelectMany variants.
bartdesmet Apr 18, 2017
5d2231a
Removing unused ObserveOn implementations.
bartdesmet Apr 18, 2017
8c67f36
Optimizing layout of Range
bartdesmet Apr 19, 2017
d6ae41d
Optimizing layouts of ToDictionary and ToLookup.
bartdesmet Apr 19, 2017
9e9efec
Removing some comments.
bartdesmet Apr 19, 2017
faa8a77
Optimizing layouts of DistinctUntilChanged.
bartdesmet Apr 19, 2017
81a05e5
Optimizing layouts of Aggregate.
bartdesmet Apr 19, 2017
d02c0b6
Optimizing layouts of Contains.
bartdesmet Apr 19, 2017
5982cab
Optimizing layouts of Timeout.
bartdesmet Apr 19, 2017
13698ed
Optimizing layouts of Throttle.
bartdesmet Apr 19, 2017
8e1d2d4
Optimizing layouts of Buffer.
bartdesmet Apr 19, 2017
b286299
Removing unused usings.
bartdesmet Apr 19, 2017
64481f9
Optimizing layouts of Window.
bartdesmet Apr 19, 2017
b6a7100
Further reduction of Window layout.
bartdesmet Apr 19, 2017
28a0d6e
Sealing the sink for Distinct.
bartdesmet Apr 19, 2017
1881892
Optimizing layouts of GroupJoin and Join.
bartdesmet Apr 19, 2017
f70ed17
Optimizing GroupBy[Until] operator layouts.
bartdesmet Apr 19, 2017
f9cab0f
Initial improvements for Delay layouts.
bartdesmet Apr 19, 2017
84ce7f7
More layout optimizations for Delay.
bartdesmet Apr 19, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,101 +7,105 @@

namespace System.Reactive.Concurrency
{
internal sealed class ObserveOn<TSource> : Producer<TSource>
internal static class ObserveOn<TSource>
{
private readonly IObservable<TSource> _source;
private readonly IScheduler _scheduler;
private readonly SynchronizationContext _context;

public ObserveOn(IObservable<TSource> source, IScheduler scheduler)
{
_source = source;
_scheduler = scheduler;
}

public ObserveOn(IObservable<TSource> source, SynchronizationContext context)
internal sealed class Scheduler : Producer<TSource>
{
_source = source;
_context = context;
}
private readonly IObservable<TSource> _source;
private readonly IScheduler _scheduler;

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "Visibility restricted to friend assemblies. Those should be correct by inspection.")]
protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
{
if (_context != null)
public Scheduler(IObservable<TSource> source, IScheduler scheduler)
{
var sink = new ObserveOnSink(this, observer, cancel);
setSink(sink);
return sink.Run();
_source = source;
_scheduler = scheduler;
}
else

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "Visibility restricted to friend assemblies. Those should be correct by inspection.")]
protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
{
var sink = new ObserveOnObserver<TSource>(_scheduler, observer, cancel);
setSink(sink);
return _source.SubscribeSafe(sink);
}
}

private sealed class ObserveOnSink : Sink<TSource>, IObserver<TSource>
internal sealed class Context : Producer<TSource>
{
private readonly ObserveOn<TSource> _parent;
private readonly IObservable<TSource> _source;
private readonly SynchronizationContext _context;

public ObserveOnSink(ObserveOn<TSource> parent, IObserver<TSource> observer, IDisposable cancel)
: base(observer, cancel)
public Context(IObservable<TSource> source, SynchronizationContext context)
{
_parent = parent;
_source = source;
_context = context;
}

public IDisposable Run()
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "2", Justification = "Visibility restricted to friend assemblies. Those should be correct by inspection.")]
protected override IDisposable Run(IObserver<TSource> observer, IDisposable cancel, Action<IDisposable> setSink)
{
//
// The interactions with OperationStarted/OperationCompleted below allow
// for test frameworks to wait until a whole sequence is observed, running
// asserts on a per-message level. Also, for ASP.NET pages, the use of the
// built-in synchronization context would allow processing to finished in
// its entirety before moving on with the page lifecycle.
//
_parent._context.OperationStarted();

var d = _parent._source.SubscribeSafe(this);
var c = Disposable.Create(() =>
{
_parent._context.OperationCompleted();
});

return StableCompositeDisposable.Create(d, c);
var sink = new _(_context, observer, cancel);
setSink(sink);
return sink.Run(_source);
}

public void OnNext(TSource value)
private sealed class _ : Sink<TSource>, IObserver<TSource>
{
_parent._context.Post(OnNextPosted, value);
}
private readonly SynchronizationContext _context;

public void OnError(Exception error)
{
_parent._context.Post(OnErrorPosted, error);
}
public _(SynchronizationContext context, IObserver<TSource> observer, IDisposable cancel)
: base(observer, cancel)
{
_context = context;
}

public void OnCompleted()
{
_parent._context.Post(OnCompletedPosted, state: null);
}
public IDisposable Run(IObservable<TSource> source)
{
//
// The interactions with OperationStarted/OperationCompleted below allow
// for test frameworks to wait until a whole sequence is observed, running
// asserts on a per-message level. Also, for ASP.NET pages, the use of the
// built-in synchronization context would allow processing to finished in
// its entirety before moving on with the page lifecycle.
//
_context.OperationStarted();

var d = source.SubscribeSafe(this);
var c = Disposable.Create(_context.OperationCompleted);

return StableCompositeDisposable.Create(d, c);
}

public void OnNext(TSource value)
{
_context.Post(OnNextPosted, value);
}

private void OnNextPosted(object value)
{
_observer.OnNext((TSource)value);
}
public void OnError(Exception error)
{
_context.Post(OnErrorPosted, error);
}

private void OnErrorPosted(object error)
{
_observer.OnError((Exception)error);
Dispose();
}
public void OnCompleted()
{
_context.Post(OnCompletedPosted, state: null);
}

private void OnCompletedPosted(object ignored)
{
_observer.OnCompleted();
Dispose();
private void OnNextPosted(object value)
{
_observer.OnNext((TSource)value);
}

private void OnErrorPosted(object error)
{
_observer.OnError((Exception)error);
Dispose();
}

private void OnCompletedPosted(object ignored)
{
_observer.OnCompleted();
Dispose();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public static IObservable<TSource> ObserveOn<TSource>(IObservable<TSource> sourc
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));

return new ObserveOn<TSource>(source, scheduler);
return new ObserveOn<TSource>.Scheduler(source, scheduler);
}

/// <summary>
Expand All @@ -120,7 +120,7 @@ public static IObservable<TSource> ObserveOn<TSource>(IObservable<TSource> sourc
if (context == null)
throw new ArgumentNullException(nameof(context));

return new ObserveOn<TSource>(source, context);
return new ObserveOn<TSource>.Context(source, context);
}

#endregion
Expand Down
29 changes: 29 additions & 0 deletions Rx.NET/Source/src/System.Reactive/Internal/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,34 @@ public static IObservable<T> Unpack<T>(IObservable<T> source)

return source;
}

public static bool All(this bool[] values)
{
foreach (var value in values)
{
if (!value)
{
return false;
}
}

return true;
}

public static bool AllExcept(this bool[] values, int index)
{
for (var i = 0; i < values.Length; i++)
{
if (i != index)
{
if (!values[i])
{
return false;
}
}
}

return true;
}
}
}
12 changes: 4 additions & 8 deletions Rx.NET/Source/src/System.Reactive/Linq/GroupedObservable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,25 @@

namespace System.Reactive.Linq
{
class GroupedObservable<TKey, TElement> : ObservableBase<TElement>, IGroupedObservable<TKey, TElement>
internal sealed class GroupedObservable<TKey, TElement> : ObservableBase<TElement>, IGroupedObservable<TKey, TElement>
{
private readonly TKey _key;
private readonly IObservable<TElement> _subject;
private readonly RefCountDisposable _refCount;

public GroupedObservable(TKey key, ISubject<TElement> subject, RefCountDisposable refCount)
{
_key = key;
Key = key;
_subject = subject;
_refCount = refCount;
}

public GroupedObservable(TKey key, ISubject<TElement> subject)
{
_key = key;
Key = key;
_subject = subject;
}

public TKey Key
{
get { return _key; }
}
public TKey Key { get; }

protected override IDisposable SubscribeCore(IObserver<TElement> observer)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ protected override IDisposable Run(IObserver<TSource> observer, IDisposable canc
return _source.SubscribeSafe(sink);
}

class _ : Sink<TSource>, IObserver<TSource>
private sealed class _ : Sink<TSource>, IObserver<TSource>
{
public _(IObserver<TSource> observer, IDisposable cancel)
: base(observer, cancel)
Expand Down
Loading