有什么更好的做我们必须异步执行方法比BlockingCollection? [英] what better do we have to asynchronous execute method than BlockingCollection?

查看:267
本文介绍了有什么更好的做我们必须异步执行方法比BlockingCollection?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了这样的例子来衡量如何快速BlockingCollection对于异步执行

 使用系统;
使用System.Collections.Concurrent;
使用System.Diagnostics程序;
使用的System.Threading;
使用System.Threading.Tasks;命名空间TestBlockingCollection
{
    类节目
    {
        静态无效的主要(字串[] args)
        {
            BlockingCollection< INT> blockingCollection =新BlockingCollection<&诠释GT;();
            秒表SW = Stopwatch.StartNew();            Task.Factory.StartNew(()=>
            {
                INT I = 0;
                而(真)
                {
                    Console.WriteLine(添加+ I);
                    SW = Stopwatch.StartNew();
                    blockingCollection.Add(我++);
                    Thread.sleep代码(1000);
                }
            });            Task.Factory.StartNew(()=>
            {
                而(真)
                {
                    INT I = blockingCollection.Take();
                    sw.Stop();
                    长微秒= sw.ElapsedTicks /(Stopwatch.Frequency /(1000L * 1000L));
                    Console.WriteLine(收到+ I + + +微秒微秒。花);
                }
            });            而(真)
            {
                Thread.sleep代码(1000);
            }
        }
    }
}

结果很失望:

 添加0
为0分花19593微秒。
加入1
1.收到花220微秒。
添加2
2.收到的花38微秒。
添加3
3.收到花104微秒。
添加4
4.收到了46微秒。
加入5
5.收到了37微秒。
加入6
6,收到的废112微秒。
添加7
7.收到的花103微秒。
添加8
8.收到的花104微秒。
添加9
9.收到的花384微秒。
加入10
10.收到的102花微秒。
添加11
11.收到了39微秒。
添加12
12.收到的花51微秒。
添加13
13.收到的花42微秒。
添加14
14.收到的花了40微秒。
加入15
15.收到的花了40微秒。
添加16
16.收到的花42微秒。
添加17
17.收到的花了40微秒。
加入18
18.收到的花41微秒。
添加19
19.收到的花42微秒。
加入20
20.收到的花62微秒。
添加21
21.收到了36微秒。
添加22
22.收到了39微秒。
添加23
23.收到了35微秒。
添加24
24.收到的花了40微秒。
加入25
25.收到的花63微秒。
添加26
26.收到的花56微秒。
添加27
27.收到的花42微秒。
添加28
28.收到的花41微秒。
添加29
29.收到的花42微秒。
加入30
30.收到的花41微秒。
添加31
31.收到的651花微秒。
添加32
32.收到了43微秒。
添加33
33.收到的花58微秒。
添加34
34.收到了43微秒。
添加35
35.收到的花41微秒。
添加36
36.收到的花59微秒。
添加37
37.收到的花38微秒。
添加38
38.收到的花38微秒。
添加39
39.收到的花38微秒。
加入40
40.收到的花42微秒。
添加41
41.收到的花59微秒。
添加42
42.收到的花了40微秒。
添加43
43.收到的花42微秒。
添加44
44.收到的花41微秒。
添加45
45.收到了39微秒。
添加46
46.​​收到的花42微秒。
添加47
47.收到的花41微秒。
添加48
48.收到的花41微秒。
添加49
49.收到的花42微秒。
加入50
50.收到了35微秒。
添加51
51.收到的花42微秒。
添加52
52.收到了39微秒。
添加53
53.收到了43微秒。
添加54
54.收到了35微秒。
添加55
55.收到的花60微秒。
添加56
56.收到的花59微秒。
添加57
57.收到的花55微秒。
添加58
58.收到的花74微秒。
添加59
59.收到的花56微秒。
添加60
60.收到的花42微秒。

在平均花了我50微秒左右,但有时我花了高达600微秒!

即使使用我慢的Pentium U5400我预计应该是恒定的几个,不超过10个,且绝不超过10微秒。

什么更快的方法.NET具有异步EXEC?异步EXEC计划后,我需要尽快开始。这是financical时间敏感的计算。

禁止收集garantees顺序和项目将被处理逐一garantees,所以这个问题实际上包含了两个问题


  1. 我们有更快的东西,如果我需要秩序,我需要的顺序来处理的项目又相继出现?即我需要FIFO查询。

  2. 请我们的东西,如果我不在乎为了更快,我不在乎,如果项目由一个或平行?
  3. 逐个处理

我猜的答案是:


  1. 没有。我必须使用BlockingCollection为引用<一个href=\"http://stackoverflow.com/questions/10103072/is-it-good-to-use-blockingcollectiont-as-single-producer-single-consumer-fifo\">is它很好用BlockingCollection&LT; T&GT;单生产者,单消费者FIFO查询?


  2. 我可能会尝试委托? http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx



解决方案

实验了好几个小时,我认为这是公司获得的方式测量后;我改成了10000运行,结果是:


  

214.0总额为100000迭代,平均0.00214毫秒


在code是pretty你高(这是下面以供参考);我做一个发布版本

我尝试使用屏障但它是慢。我也试着只用锁做,但未能得到该工作。

 静态无效的主要(字串[] args)
    {
        VAR屏障=新的屏障(2);
        VAR收集=新的List&LT; INT&GT;();
        VAR num_iterations = 100000;
        VAR迭代= num_iterations;
        VAR total_time_ms = 0.0M;        秒表SW =新的秒表();
        total_time_ms = 0.0M;
        迭代= num_iterations;        VAR blockingCollection =新BlockingCollection&LT;&诠释GT;();        Task.Factory.StartNew(()=&GT;
        {
            INT I = 0;            而(iterations--大于0)
            {
                sw.Restart();
                blockingCollection.Add(我++);
            }
        });
        Task.Factory.StartNew(()=&GT;
        {
            变种expected_value = 0;            当执行//停止一定数量;而(0迭代&GT)
            {
                INT I = blockingCollection.Take();
                sw.Stop();
                长微秒= sw.ElapsedTicks /(Stopwatch.Frequency /(1000L * 1000L));
                total_time_ms + =微秒;
                如果(我!= expected_value)
                    Console.WriteLine(的String.Format(**预期{0}有{1},我,expected_value));
                expected_value ++;
            }
        });
        而(迭代大于0)
        {
            Thread.sleep代码(1000);
        }
        Console.WriteLine(的String.Format(共有{0} {1}迭代,平均{2},total_time_ms,num_iterations,total_time_ms / num_iterations));

我相信BlockingCollection是一个很好的集合,用于此。这样做有它的其他方式,但这是一个复杂的区域,得到的东西比这更快的机会是不太可能的。

I wrote such example to measure how fast BlockingCollection for asynchronous execution

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace TestBlockingCollection
{
    class Program
    {
        static void Main(string[] args)
        {
            BlockingCollection<int> blockingCollection = new BlockingCollection<int>();
            Stopwatch sw = Stopwatch.StartNew();

            Task.Factory.StartNew(() =>
            {
                int i = 0;
                while (true)
                {
                    Console.WriteLine("Adding " + i);
                    sw = Stopwatch.StartNew();
                    blockingCollection.Add(i++);
                    Thread.Sleep(1000);
                }
            });

            Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    int i = blockingCollection.Take();
                    sw.Stop();
                    long microseconds = sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
                    Console.WriteLine("Received " + i + ". Spent " + microseconds + " microseconds.");
                }
            });

            while(true)
            {
                Thread.Sleep(1000);
            }
        }
    }
}

Results are disappointing:

Adding 0
Received 0. Spent 19593 microseconds.
Adding 1
Received 1. Spent 220 microseconds.
Adding 2
Received 2. Spent 38 microseconds.
Adding 3
Received 3. Spent 104 microseconds.
Adding 4
Received 4. Spent 46 microseconds.
Adding 5
Received 5. Spent 37 microseconds.
Adding 6
Received 6. Spent 112 microseconds.
Adding 7
Received 7. Spent 103 microseconds.
Adding 8
Received 8. Spent 104 microseconds.
Adding 9
Received 9. Spent 384 microseconds.
Adding 10
Received 10. Spent 102 microseconds.
Adding 11
Received 11. Spent 39 microseconds.
Adding 12
Received 12. Spent 51 microseconds.
Adding 13
Received 13. Spent 42 microseconds.
Adding 14
Received 14. Spent 40 microseconds.
Adding 15
Received 15. Spent 40 microseconds.
Adding 16
Received 16. Spent 42 microseconds.
Adding 17
Received 17. Spent 40 microseconds.
Adding 18
Received 18. Spent 41 microseconds.
Adding 19
Received 19. Spent 42 microseconds.
Adding 20
Received 20. Spent 62 microseconds.
Adding 21
Received 21. Spent 36 microseconds.
Adding 22
Received 22. Spent 39 microseconds.
Adding 23
Received 23. Spent 35 microseconds.
Adding 24
Received 24. Spent 40 microseconds.
Adding 25
Received 25. Spent 63 microseconds.
Adding 26
Received 26. Spent 56 microseconds.
Adding 27
Received 27. Spent 42 microseconds.
Adding 28
Received 28. Spent 41 microseconds.
Adding 29
Received 29. Spent 42 microseconds.
Adding 30
Received 30. Spent 41 microseconds.
Adding 31
Received 31. Spent 651 microseconds.
Adding 32
Received 32. Spent 43 microseconds.
Adding 33
Received 33. Spent 58 microseconds.
Adding 34
Received 34. Spent 43 microseconds.
Adding 35
Received 35. Spent 41 microseconds.
Adding 36
Received 36. Spent 59 microseconds.
Adding 37
Received 37. Spent 38 microseconds.
Adding 38
Received 38. Spent 38 microseconds.
Adding 39
Received 39. Spent 38 microseconds.
Adding 40
Received 40. Spent 42 microseconds.
Adding 41
Received 41. Spent 59 microseconds.
Adding 42
Received 42. Spent 40 microseconds.
Adding 43
Received 43. Spent 42 microseconds.
Adding 44
Received 44. Spent 41 microseconds.
Adding 45
Received 45. Spent 39 microseconds.
Adding 46
Received 46. Spent 42 microseconds.
Adding 47
Received 47. Spent 41 microseconds.
Adding 48
Received 48. Spent 41 microseconds.
Adding 49
Received 49. Spent 42 microseconds.
Adding 50
Received 50. Spent 35 microseconds.
Adding 51
Received 51. Spent 42 microseconds.
Adding 52
Received 52. Spent 39 microseconds.
Adding 53
Received 53. Spent 43 microseconds.
Adding 54
Received 54. Spent 35 microseconds.
Adding 55
Received 55. Spent 60 microseconds.
Adding 56
Received 56. Spent 59 microseconds.
Adding 57
Received 57. Spent 55 microseconds.
Adding 58
Received 58. Spent 74 microseconds.
Adding 59
Received 59. Spent 56 microseconds.
Adding 60
Received 60. Spent 42 microseconds.

In average I spent about 50 microseconds, but sometimes I spent up to 600 microseconds!

Even using my slow Pentium U5400 I expect that should be constant of several, not more than 10, and never more than 10 microseconds.

What faster method .NET has for async exec? After async exec scheduled I need it to start asap. This is financical time-sensitive calculations.

Blocking collection garantees order and garantees that items will be processed one by one, so this question contains actually two question

  1. Do we have something faster if I NEED order and I NEED items to be processed in the order they have appeared? I.e. I need FIFO query.
  2. Do we have something faster if I don't care about order and I don't care if items processed one by one or parallely?

I guess that answers are:

  1. No. I have to use BlockingCollection for that refer is it good to use BlockingCollection<T> as single-producer, single-consumer FIFO query?

  2. I can probably try delegates? http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx

解决方案

After a good few hours of experimentation I think it's the measurement that's getting in the way; I changed it to run for 10000 and the results are:

Total 214.0 for 100000 iterations, average 0.00214 ms

The code is pretty much as yours (it's below for reference); I did do a release build

I experimented with using a Barrier but it was slower. I also tried to do it using just locks but failed to get that working.

   static void Main(string[] args)
    {
        var barrier = new Barrier(2);
        var collection = new List<int>();
        var num_iterations = 100000;
        var iterations = num_iterations;
        var total_time_ms = 0.0M;

        Stopwatch sw = new Stopwatch();


        total_time_ms = 0.0M;
        iterations = num_iterations;

        var blockingCollection = new BlockingCollection<int>();

        Task.Factory.StartNew(() =>
        {
            int i = 0;

            while (iterations-- > 0)
            {
                sw.Restart();
                blockingCollection.Add(i++);
            }
        });


        Task.Factory.StartNew(() =>
        {
            var expected_value = 0;

            while (iterations > 0) // stop when performed certain number
            {
                int i = blockingCollection.Take();
                sw.Stop();
                long microseconds = sw.ElapsedTicks / (Stopwatch.Frequency / (1000L * 1000L));
                total_time_ms += microseconds;
                if (i != expected_value)
                    Console.WriteLine(String.Format("** expected {0} got {1}", i, expected_value));
                expected_value++;
            }
        });
        while (iterations > 0)
        {
            Thread.Sleep(1000);
        }
        Console.WriteLine(String.Format("Total {0} for {1} iterations, average {2}", total_time_ms, num_iterations, total_time_ms / num_iterations));

I believe that BlockingCollection is a good collection to use for this. There are other ways of doing it but this is a complicated area and the chances of getting something faster than this are unlikely.

这篇关于有什么更好的做我们必须异步执行方法比BlockingCollection?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆