我已经实现了一种非常幼稚的内存扇出排队机制,如下所示:
public class ObservableQueue<T> : IObservableQueue<T>
{
private readonly Subject<T> queue;
public IObservable<T> Messages => queue.AsObservable();
public ObservableQueue()
{
queue = new Subject<T>();
}
public void Enqueue(T item)
{
queue.OnNext(item);
}
public void Enqueue(List<T> items)
{
items.ForEach(queue.OnNext);
}
}
我之所以选择此实现,是因为它允许极具表现力的订阅,我非常喜欢这种订阅,如下所示:
subscription = queue.Messages
.Select(data => data.ToJson())
.Buffer(TimeSpan.FromSeconds(10), ByteSize.FromBytes(128))
.Where(Enumerable.Any)
.Select(ToQuery)
.Subscribe(query => db.Execute(query));
这里使用的Buffer
方法再次是我的一个天真的实现:
public static IObservable<IList<string>> Buffer(this IObservable<string> source, TimeSpan timeSpan, ByteSize size)
{
// Completes when the `timespan` has elapsed
var timer = Observable.Timer(timeSpan).Select(_ => new Unit());
// Completes when the ByteSize exceeds `size`
var bytes = source
.Scan(ByteSize.FromBytes(0),
(a, b) => a + ByteSize.FromBytes(Encoding.Unicode.GetByteCount(b)))
.SkipWhile(a => a < size)
.Select(_ => new Unit()); // We only want to use these for notification, and both observables
// need to be of the same type, so we just emit Unit
// Amb races the two observables to see which one finishes first, which then propagates the notification
// and signals the source to strop buffering
return source.Buffer(() => Observable.Amb(timer, bytes));
}
现在,当我在第二个代码块中创建预订时,内存使用量将急剧增加,罪魁祸首是Subject<T>
中的ObservableQueue<T>
。我要强调一点,此时尚未Enqueue
d实际数据。 subscription
已创建,仍在等待任何数据实际处理。
我可以在这里看到一些潜在的罪魁祸首:
queue.AsObservable()
Buffer
方法subscription
寿命长的事实但是,我还无法在这里查明实际的根本原因。有什么想法吗?
注意:我认为很明显我不太了解System.Reactive
,因此,如果我在这里写了些愚蠢的东西,我会道歉。