I am writing a piece of software which is modelling trains and train station departure boards. The trains store how many minutes ahead of / behind schedule they are. Each instance of the departure board subscribes to a constantly changing subset of trains.
我正在写一个模拟火车和火车站出发板的软件。火车存储的时间提前了多少分钟。出发板的每个实例都订阅了不断变化的列车子集。
We are writing the application to be able to handle tens of thousands of trains and hundreds of thousands (possibly millions) of departure boards.
我们正在编写应用程序,以便能够处理成千上万的列车和数十万(可能是数百万)的出发板。
Rather than have the trains maintain a list of references to each subscribing departure board, my plan was to use .NET events. Each time some information about the scheduling of the train changes, the instance of the train class raises an event. Each instance of the Departure Board class simply adds or removes event listeners for trains to which they are subscribing.
我的计划是使用.NET事件,而不是让列车保留每个订阅出发板的参考列表。每当关于列车的调度的一些信息改变时,列车类的实例引发事件。离境委员会班级的每个实例都只是添加或删除他们订阅的列车的事件监听器。
Is there a limit to how many listeners an event can have? If so, what is the limit and how will performance degrade?
事件可以拥有多少听众?如果是这样,那么限制是什么,性能如何降低?
Thanks, Rik
谢谢,Rik
2 个解决方案
#1
2
Well, here's some code that adds a million handlers to a delegate and it works fine:
好吧,这里有一些代码可以为委托添加一百万个处理程序,它运行正常:
Action<int> action = n => Console.WriteLine(n);
for (var i = 0; i <= 1000000; i++)
{
var i2 = i;
action += n => Console.WriteLine(n + i2);
}
action(42);
I would, however, look at using Microsoft's Reactive Extensions, rather than raw events, to handle your eventing. Using delegate will get incredibly difficult to perform any kind of aggregation and filtering at the scale you're talking about.
但是,我会考虑使用Microsoft的Reactive Extensions而不是原始事件来处理您的事件。使用委托将难以置信地以您所讨论的规模执行任何类型的聚合和过滤。
#2
1
Is there a limit to how many listeners an event can have?
事件可以拥有多少听众?
How much memory have you got? ;p In terms of the numbers you're talking about, it should be fine - but frankly I don't think that it is a great approach. But:
你有多少记忆? ; p就你所谈论的数字而言,应该没问题 - 但坦率地说,我不认为这是一个很好的方法。但:
static void Main()
{
EventHandler handler = null;
for (int i = 0; i < 6000000; i++)
{
var obj = new Spoof();
handler += obj.Bar;
if ((i % 1000) == 0) Console.WriteLine(i);
}
Console.WriteLine("done");
Console.ReadKey();
handler(null, null);
}
class Spoof
{
public void Bar(object sender, EventArgs args) { Console.WriteLine("hi"); }
}
If so, what is the limit and how will performance degrade?
如果是这样,那么限制是什么,性能如何降低?
Basically, approximately linearly.
基本上,近似线性。
However, I really don't think this approach is ideal - it has issues such as being limited to a single app-domain (making it hard to distribute between nodes), and it is really easy to get unexpected memory scenarios when using events like that. Also, unsubscribing will get pretty expensive since it needs to scan the subscriber list.
但是,我真的不认为这种方法是理想的 - 它有一些问题,例如仅限于单个应用程序域(使得难以在节点之间分配),并且在使用类似事件时很容易获得意外的内存情况那。此外,取消订阅将变得非常昂贵,因为它需要扫描订户列表。
Personally, I'd be using something like redis pub/sub, or some other dedicated pub/sub system. The boards could subscribe to trains (or maybe lines) they're interested in, and trains (or lines) just broadcast to those named channels.
就个人而言,我会使用像redis pub / sub或其他一些专用的pub / sub系统。董事会可以订阅他们感兴趣的火车(或者可能是线路),并且火车(或线路)只是广播到那些命名的频道。
#1
2
Well, here's some code that adds a million handlers to a delegate and it works fine:
好吧,这里有一些代码可以为委托添加一百万个处理程序,它运行正常:
Action<int> action = n => Console.WriteLine(n);
for (var i = 0; i <= 1000000; i++)
{
var i2 = i;
action += n => Console.WriteLine(n + i2);
}
action(42);
I would, however, look at using Microsoft's Reactive Extensions, rather than raw events, to handle your eventing. Using delegate will get incredibly difficult to perform any kind of aggregation and filtering at the scale you're talking about.
但是,我会考虑使用Microsoft的Reactive Extensions而不是原始事件来处理您的事件。使用委托将难以置信地以您所讨论的规模执行任何类型的聚合和过滤。
#2
1
Is there a limit to how many listeners an event can have?
事件可以拥有多少听众?
How much memory have you got? ;p In terms of the numbers you're talking about, it should be fine - but frankly I don't think that it is a great approach. But:
你有多少记忆? ; p就你所谈论的数字而言,应该没问题 - 但坦率地说,我不认为这是一个很好的方法。但:
static void Main()
{
EventHandler handler = null;
for (int i = 0; i < 6000000; i++)
{
var obj = new Spoof();
handler += obj.Bar;
if ((i % 1000) == 0) Console.WriteLine(i);
}
Console.WriteLine("done");
Console.ReadKey();
handler(null, null);
}
class Spoof
{
public void Bar(object sender, EventArgs args) { Console.WriteLine("hi"); }
}
If so, what is the limit and how will performance degrade?
如果是这样,那么限制是什么,性能如何降低?
Basically, approximately linearly.
基本上,近似线性。
However, I really don't think this approach is ideal - it has issues such as being limited to a single app-domain (making it hard to distribute between nodes), and it is really easy to get unexpected memory scenarios when using events like that. Also, unsubscribing will get pretty expensive since it needs to scan the subscriber list.
但是,我真的不认为这种方法是理想的 - 它有一些问题,例如仅限于单个应用程序域(使得难以在节点之间分配),并且在使用类似事件时很容易获得意外的内存情况那。此外,取消订阅将变得非常昂贵,因为它需要扫描订户列表。
Personally, I'd be using something like redis pub/sub, or some other dedicated pub/sub system. The boards could subscribe to trains (or maybe lines) they're interested in, and trains (or lines) just broadcast to those named channels.
就个人而言,我会使用像redis pub / sub或其他一些专用的pub / sub系统。董事会可以订阅他们感兴趣的火车(或者可能是线路),并且火车(或线路)只是广播到那些命名的频道。