带有Max Parallelism

时间:2017-02-22 17:40:15

标签: c# system.reactive observable concat reactive

我正在从数据库中读取时间序列数据,但这些数据点是不同位置的分区。因此,例如,如果存在1 Hz数据,则每3600个数据点(一小时)存储在不同的分区中。当我读取这些数据点时,我必须以正确的逻辑顺序将它们返回给用户。因此,我必须返回3600个数据点,时间为00:00,然后是3600个数据点,时间为01:00,...直到23:00。当然,数据库查询会有延迟。假设每个查询都是10毫秒。这意味着如果我做concat,它会有24 * 10 ms = 240 ms的延迟。我需要的是一个具有许多并行性的热连接。我无法按顺序执行所有这些查询,然后执行常规连接,因为用户可能需要1年的数据。 目前,我所拥有的是这样的:

public IObservable<int> ReadSensorPartitions( /* Guid sensorId*/)
        {
            return Observable.Create<int>(async o =>
            {
                try
                {
                    await Task.Delay(10).ConfigureAwait(false);
                    Observable.Range(1, 1000).Subscribe(o);
                }
                catch (Exception e)
                {
                    o.OnError(e);
                }
            });
        }

        public IObservable<int> ReadSensorData(int partitionNum)
        {
            return Observable.Create<int>(async o =>
            {
                try
                {
                    await Task.Delay(10).ConfigureAwait(false);
                    Observable.Range(partitionNum*1000, 999).Subscribe(o);
                }
                catch (Exception e)
                {
                    o.OnError(e);
                }
            });
        }

        public IObservable<int> ConcatObservables(IObservable<IObservable<int>> observables)
        {
            return ReadSensorPartitions().Select(partitionNum => ReadSensorData(partitionNum)).Concat();
        } 

        public async Task TestConcatObservables()
        {
            var taskCompletionSource = new TaskCompletionSource<bool>();
            long count = 0;
            var sw = Stopwatch.StartNew();
            ConcatObservables(ReadSensorPartitions().Select(partitionNum => ReadSensorData(partitionNum)))
                .Subscribe(x =>
                {
                    count++;
                }, ex =>
                {

                }, () =>
                {
                    taskCompletionSource.SetResult(true);
                });
            await taskCompletionSource.Task.ConfigureAwait(false);
            sw.Stop();
            Console.WriteLine("TestConcatObservables Duration for {0} datapoint(s) is {1} ms", count, sw.Elapsed.TotalMilliseconds);
        }

对于1年的数据,这将至少需要87.6秒。我需要这样的东西

public IObservable<int> HotConcatObservables(IObservable<IObservable<int>> observables, int parallelism)
        {

        }

例如,如果将并行性设置为24,则前24个读取立即全部预热并缓冲。我们返回分区1,然后是2,...直到24,一旦分区1完成流式传输,我们立即预热分区25.一旦分区2完成流式传输,我们就预热分区26等等。所有这些数据点都必须返回按照正确的逻辑顺序。

我花了很多时间来做这件事,但我做的最好(使用IConnectableObservable)比Merge慢5倍(即使并行性是相同数量的分区)。无论如何还有。这可以有效地完成吗?我真的非常感谢你提供任何帮助。

0 个答案:

没有答案