我们有一个非常高性能的多任务处理,近乎实时的C#应用程序.这种性能主要通过在内部与本土调度程序一起实施协作式多任务处理来实现.这通常被称为微线程.在该系统中,所有任务都通过队列与其他任务进行通信.
我们所遇到的具体问题似乎只能通过C#不支持的一流延续来解决.
具体而言,问题出现在处理队列的2个案例中.每当任何特定任务在将项目放入队列之前执行某些工作时.如果队列已满,该怎么办?
相反,一个不同的任务可能会做一些工作,然后需要从队列中取出一个项目.如果那个队列是空的怎么办?
我们已经在90%的情况下通过将队列链接到任务来解决这个问题,以避免在任何出站队列已满或入站队列为空时调用任务.
此外,某些任务被转换为状态机,因此如果队列已满/空,它们可以处理并继续而无需等待.
真正的问题出现在一些边缘情况下,其中任何一种解决方案都是不切实际的.在这种情况下的想法是在该点保存堆栈状态并切换到另一个任务,以便它可以完成工作,并随后在能够继续时重试等待任务.
在过去,我们尝试将等待任务调用回调度(递归)以允许其他任务以及稍后重试等待任务.然而,这导致了太多的"僵局"情况.
有一个自定义CLR主机的示例,使.NET线程实际上作为"光纤"运行,这实际上允许在线程之间切换堆栈状态.但现在我似乎无法找到任何示例代码.此外,似乎需要一些重要的复杂性才能做到正确.
有没有人有任何其他创意,如何有效地切换任务,避免上述问题?
是否有其他CLR主机提供此商业或其他?是否有任何附加本机库可以为C#提供某种形式的延续?
我有一个阻塞队列的对象.
我想写一个阻塞的线程,直到队列中有一个对象.与BlockingQueue.take()提供的功能类似.
但是,由于我不知道我是否能够成功处理对象,我想只是peek()而不是删除对象.我想删除该对象只有我能够成功处理它.
所以,我想要一个阻塞的peek()函数.目前,peek()只是在队列为空时根据javadoc返回.
我错过了什么吗?还有其他方法可以实现此功能吗?
编辑:
如果我只是使用了一个线程安全队列并且偷看和睡觉了?
public void run() {
while (!exit) {
while (queue.size() != 0) {
Object o = queue.peek();
if (o != null) {
if (consume(o) == true) {
queue.remove();
} else {
Thread.sleep(10000); //need to backoff (60s) and try again
}
}
}
Thread.sleep(1000); //wait 1s for object on queue
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我只有一个消费者线程和一个(单独的)生产者线程.我想这不如使用BlockingQueue有效......任何评论都赞赏.
目前我从我的存储中获取"列表"数据,"解除"它以使用该数据.在处理获取的数据后,我必须将它们放回存储器中.只要我没有强迫(至少我认为如此)使用python的标准"list"对象来保存这些数据,这就不会有问题了.
存储服务:Google Appengine.
我的解决方法是:
dequeObj = deque(myData)
my_list= list()
for obj in dequeObj:
my_list.append(obj)
Run Code Online (Sandbox Code Playgroud)
但这似乎不是很理想.
他们之间有什么区别?我知道
队列设计为在队列末尾插入元素,并从队列的开头删除元素.Dequeue表示一个队列,您可以在其中插入和删除队列两端的元素.
但哪个效率更高?
加上他们两个有什么区别?因为我对它们有一些了解,我上面说过,但我想了解更多关于它们的信息.我们将不胜感激.
如何实现一个循环列表,当它填满时覆盖最旧的条目?
对于一点背景,我想在GWT中使用循环列表; 所以使用第三方库不是我想要的.
下面有一点长的描述,但这是一个非常棘手的问题.我试图覆盖我们对该问题的了解,以缩小搜索范围.问题更多的是正在进行的调查,而不是基于单一问题的调查,但我认为它也可能有助于其他人.但如果您认为我对下面的某些假设有误,请在评论中添加信息或纠正我.
更新2013年2月19日:我们已经清除了一些问号,我有一个理论,我将在下面更新主要问题.但是还没准备好写一个"已解决"的回复.
2013年4月24日更新:现在生产稳定(虽然我认为这是暂时的),但我认为这是由于两个原因造成的.1)端口增加,2)减少传出(转发)请求的数量.我会在正确的背景下继续这个更新.
我们目前正在我们的生产环境中进行调查,以确定当进行太多传出异步Web服务请求时,我们的IIS Web服务器无法扩展(一个传入请求可能会触发多个传出请求).
CPU只有20%,但我们收到传入请求的HTTP 503错误,许多传出的Web请求得到以下异常:"SocketException:无法执行套接字上的操作,因为系统缺少足够的缓冲区空间或因为队列是"显然,某个地方存在可扩展性瓶颈,我们需要找出它是什么以及是否有可能通过配置来解决它.
应用背景:
我们在Windows 2008 R2 64位操作系统上使用.NET 4.5运行IIS v7.5集成托管管道.我们在IIS中只使用了一个工作进程.硬件略有不同,但用于检查错误的机器是Intel Xeon 8核心(16个超线程).
我们使用异步和同步Web请求.那些异步的是使用新的.NET异步支持来使每个传入请求在应用程序中向持久化TCP连接上的其他服务器发出多个HTTP请求(保持活动状态).同步请求执行时间低0-32 ms(由于线程上下文切换而发生更长时间).对于异步请求,在请求中止之前,执行时间最长可达120毫秒.
通常,每台服务器最多可以提供约1000个传入请求.当问题开始出现时,传出请求是~300个请求/秒,最多约600个请求/秒.仅在传出异步时才会出现问题.请求在服务器上启用,我们超过一定级别的传出请求(~600 req./s).
解决问题的可能方法:
在这个问题上搜索互联网揭示了许多可能的候选解决方案.但是,它们非常依赖于.NET,IIS和操作系统的版本,所以在我们的上下文中找到一些东西需要时间(anno 2013).
下面列出了解决方案候选人以及我们迄今为止在配置背景方面得出的结论.到目前为止,我已将检测到的问题区域分类为以下主要类别:
传出的异步请求异常消息确实指示某个缓冲区队列已被填满.但它没有说哪个队列/缓冲区.通过IIS论坛(以及那里引用的博客文章),我已经能够在下面标记为AF的请求管道中区分4个可能的6个(或更多)不同类型的队列.
虽然应该说明所有下面定义的队列,我们可以肯定地看到1.B)ThreadPool性能计数器Requests Queued在有问题的负载期间变得非常满.因此问题的原因可能是.NET级别而不是低于此级别(CF).
我们使用.NET框架类WebClient发出异步调用(异步支持),而不是我们遇到的HttpClient具有相同的问题,但具有低得多的req/s阈值.我们不知道.NET Framework实现是否隐藏任何内部队列或不在线程池之上.我们认为情况并非如此.
线程池充当自然队列,因为.NET线程(默认)调度程序正从线程池中挑选线程以执行.
性能计数器:[ASP.NET v4.0.30319].[请求排队].
配置可能性:
如果线程池已满,请求将开始堆积在此本机(未管理)队列中.
性能计数器: [ASP.NET v4.0.30319].[本机队列中的请求]
配置可能性: ????
此队列与上面的1.C)队列不同.这是我所说的解释"HTTP.sys内核队列本质上是一个完成端口,用户模式(IIS)从内核模式(HTTP.sys)接收请求.它有一个队列限制,当超过该限制时,您将收到503状态代码.HTTPErr日志还将通过记录503状态和QueueFull来指示这发生了.
性能计数器: …
我有一个线程将事件推送到第二个线程的传入队列的经典问题.只有这一次,我对表现很感兴趣.我想要实现的是:
我的第一个想法是使用a LinkedBlockingQueue,但我很快意识到它不是并发的,而且性能受到了影响.在另一方面,我现在使用ConcurrentLinkedQueue,但还是我付出的成本wait()/ notify()每本出版物上.由于消费者在找到空队列时没有阻止,因此我必须同步并wait()锁定.另一方面,制作人必须获得锁定并notify()在每一个出版物上.总体结果是sycnhronized (lock) {lock.notify()},即使不需要,我也会支付每一份出版物的费用
.
我猜这里需要的是一个阻塞和并发的队列.我想象一个push()操作工作ConcurrentLinkedQueue,notify()当推送元素是列表中的第一个时,对象的额外内容.这种检查我认为已经存在ConcurrentLinkedQueue,因为推动需要连接下一个元素.因此,这比每次在外部锁上同步要快得多.
是这样的/合理的吗?
我正在Albahari兄弟的Nutshell中阅读C#4.0,我发现了这个:
堆栈在内部实现,其数组根据需要调整大小,与Queue和List一样.(第288页,第4段)
我不禁想知道为什么.LinkedList提供O(1)头尾插入和删除(这应该适用于堆栈或队列).可调整大小的数组有O(1)缓冲插入(如果我没记错的话),但O(n)最坏的情况(我不确定删除).它可能比链表使用更多的空间(对于大型堆栈/队列).
还有更多吗?双链表实现的缺点是什么?
我有兴趣知道实现基于线程的队列的最佳方法是什么.
例如:
我有10个动作,我想用4个线程执行.我想创建一个队列,其中所有10个动作都是线性放置的,并且用4个线程开始前4个动作,一旦一个线程完成执行,下一个将启动等 - 所以一次,线程的数量是4或小于4.
queue ×10
c# ×3
java ×3
.net ×2
deque ×2
asp.net ×1
asynchronous ×1
blocking ×1
c ×1
concurrency ×1
generic-list ×1
iis ×1
linked-list ×1
list ×1
multitasking ×1
object ×1
peek ×1
python ×1
ruby ×1
stack ×1