【问题标题】:Measuring response time using observables使用 observables 测量响应时间
【发布时间】:2017-07-22 14:11:19
【问题描述】:

给定表示传入请求的 Observable A ...

interface IRequest
{
  string Id { get; }
}

IObservable<IRequest> requests;

和表示响应的 Observable B ...

IObservable<string> responses;

我需要测量产生响应所需的时间。我当前的解决方案如下所示。这可行,但我不确定这是否可以简化或更简化。我还担心实际响应时间 ([GEN]) 和观察到的响应时间 ([OBS]) 之间的偏差,如果将 generatedResponseTime 设置为低于 50 毫秒,这种偏差就会变得非常显着。

class Program
{
    public class Request
    {
        public string Id { get; set; }
    }

    static void Main(string[] args)
    {
        var generatedResponseTime = 100;

        var responseSub = new Subject<string>();

        IObservable<Request> requests = Observable.Interval(TimeSpan.FromMilliseconds(1000))
            .Select(x=> new Request { Id = x.ToString("d") });

        IObservable<string> responses = responseSub.AsObservable();

        var responseTime = requests
            .Where(x => !string.IsNullOrEmpty(x.Id))
            .Select(req => new { Id = req.Id, Start = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() })
            .SelectMany(req => responses
                .Where(reqId => reqId == req.Id)
                .Select(_ => new { RequestId = req.Id, ResponseTime = (int)(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - req.Start) })
                .Take(1))
            .Publish()
            .RefCount();

        requests.ObserveOn(TaskPoolScheduler.Default)
            .Subscribe(req =>
            {
                Console.WriteLine($"[GEN] {req.Id} = {generatedResponseTime} ms");

                Thread.Sleep(generatedResponseTime);
                responseSub.OnNext(req.Id);
            });

        responseTime.Subscribe(x => Console.WriteLine($"[OBS] {x.RequestId} = {x.ResponseTime} ms"));

        Console.ReadLine();
    }
}

【问题讨论】:

  • 您能否为此提供minimal reproducible example?我可以复制、粘贴和运行以查看代码的工作原理吗?
  • 这是我见过的最好的minimal reproducible example 之一。为此 +1!
  • 你为什么有.Publish().RefCount()
  • @Enigmativity 只是因为使用它的现实世界项目有多个订阅者观察这个和其他几个遥测流。
  • 你使用的真正的requests 是一个永远不会完成的可观察对象吗?

标签: c# system.reactive reactive-programming


【解决方案1】:

这是使用一些内置运算符的替代方法。在您的解决方案中也没有多个订阅问题:

var responseTime2 = requests
    .Timestamp()
    .Join(responses.Timestamp(),
        request => Observable.Never<Unit>(), //timeout criteria
        response => Observable.Empty<Unit>(),
        (request, response) => (request: request, response: response)
    )
    .Where(t => t.request.Value.Id == t.response.Value)
    .Select(t => t.response.Timestamp.ToUnixTimeMilliseconds() - t.request.Timestamp.ToUnixTimeMilliseconds())

如果您对请求有任何类型的超时标准,那么从性能角度来看,将其放在注释指示的位置会很有帮助。否则Join/Where 组合的性能会随着时间的推移而恶化。

【讨论】:

    猜你喜欢
    • 2020-11-16
    • 2020-12-27
    • 2016-07-10
    • 1970-01-01
    • 2013-03-18
    • 2020-08-02
    • 1970-01-01
    • 2011-10-20
    • 1970-01-01
    相关资源
    最近更新 更多