小编Mic*_*lli的帖子

读取由Interlocked在其他线程上更新的int

(这是重复:如何正确读取Interlocked.Increment'ed int字段?但是,在阅读了答案和评论之后,我仍然不确定正确的答案.)

有些代码我不拥有,也无法更改为使用在几个不同线程中增加int计数器(numberOfUpdates)的锁.所有通话都使用:

Interlocked.Increment(ref numberOfUpdates);
Run Code Online (Sandbox Code Playgroud)

我想在我的代码中读取numberOfUpdates.既然这是一个int,我知道它不会撕裂.但是,确保我获得最新价值的最佳方法是什么?看起来我的选择是:

int localNumberOfUpdates = Interlocked.CompareExchange(ref numberOfUpdates, 0, 0);
Run Code Online (Sandbox Code Playgroud)

要么

int localNumberOfUpdates = Thread.VolatileRead(numberOfUpdates);
Run Code Online (Sandbox Code Playgroud)

两者都有效(无论优化,重新排序,缓存等,都可以提供最新的价值)?一个比另一个更受欢迎吗?还有第三种选择更好吗?

.net c# multithreading interlocked interlocked-increment

35
推荐指数
3
解决办法
1万
查看次数

VS2015升级后垃圾收集和Parallel.ForEach问题

我有一些代码可以在我自己的R-like C#DataFrame类中处理数百万个数据行.有许多Parallel.ForEach调用并行迭代数据行.这段代码使用VS2013和.NET 4.5运行了一年多没有问题.

我有两台开发机器(A和B),最近升级了机器A到VS2015.大约一半时间我开始注意到我的代码中出现了一个奇怪的间歇性冻结.让它运行很长一段时间,事实证明代码最终会完成.它只需要15-120分钟而不是1-2分钟.

使用VS2015调试器尝试全部中断由于某种原因而失败.所以我插入了一堆日志语句.事实证明,在Parallel.ForEach循环期间存在Gen2集合时会发生此冻结(比较每个Parallel.ForEach循环之前和之后的集合计数).整个额外的13-118分钟用于任何Parallel.ForEach循环调用恰好与Gen2集合(如果有的话)重叠.如果在任何Parallel.ForEach循环期间没有Gen2集合(大约50%的时间运行它),那么一切都会在1-2分钟内完成.

当我在机器A上的VS2013中运行相同的代码时,我得到了相同的冻结.当我在机器B(从未升级过)的VS2013中运行代码时,它运行得很好.它一夜之间没有结冰了几十次.

我注意到/试过的一些事情:

  • 无论是否在机器A上附加了调试器,都会发生冻结(我认为它首先是VS2015调试器的东西)
  • 无论我是在构建调试还是在发布模式下,都会发生冻结
  • 如果我的目标是.NET 4.5或.NET 4.6,就会发生冻结
  • 我试过禁用RyuJIT,但这并没有影响冻结

我根本没有改变默认的GC设置.根据GCSettings,所有运行都发生在LatencyMode Interactive和IsServerGC为假.

我可以在每次调用Parallel.ForEach之前切换到LowLatency,但我真的更愿意了解正在发生的事情.

在VS2015升级之后,有没有其他人在Parallel.ForEach中看到过奇怪的冻结?关于下一步会有什么好处的任何想法?

更新1:在上面的模糊解释中添加一些示例代码...

以下是一些示例代码,我希望能够证明这个问题.此代码在B机器上运行10-12秒,始终如一.它遇到了许多Gen2系列,但它们几乎没有时间.如果我取消注释两个GC设置行,我可以强制它没有Gen2集合.它比30-50秒慢一些.

现在在我的A机器上,代码需要一段随机的时间.似乎是5到30分钟.它似乎变得更糟,它遇到的Gen2系列越多.如果我取消注释两个GC设置行,则机器A也需要30-50秒(与机器B相同).

可能需要对行数和数组大小进行一些调整才能显示在另一台机器上.

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using System.Runtime;    

public class MyDataRow
{
    public int Id { get; set; }
    public double Value { get; set; }
    public double DerivedValuesSum { get; set; }
    public double[] DerivedValues { get; set; }
}

class Program
{
    static void Example()
    {
        const …
Run Code Online (Sandbox Code Playgroud)

c# garbage-collection parallel.foreach visual-studio-2015 .net-4.6

34
推荐指数
3
解决办法
3714
查看次数

适用于Windows和Linux的同一台机器上的套接字

与Windows和Linux上的命名管道和其他方法相比,在执行IPC时使用套接字的效率如何?

现在,我在4个需要通信的独立盒子上有4个独立的应用程序.两个是在Windows Server 2003 R2上运行的.NET 3.5应用程序.两个是Linux(Suse Linux 10).它们通常不受CPU限制.流量不是很大,但非常重要的是低延迟.我们现在正在使用套接字,nagle dis-abled和linux机器上安装的sles10慢启动补丁.

你认为我们可以通过简单地在相同的Windows机器上运行两个Windows应用程序和同一个Linux机器上的两个Linux应用程序并且不进行代码更改(即仍然使用套接字)来获得多少速度提升.

操作系统是否会意识到端点位于同一台机器上,并且知道不通过数据包进入以太网?他们的数据包是否仍然需要通过整个网络堆栈?如果我们花时间更改命名管道或内存映射文件或其他东西,速度会快多少?

c# sockets linux networking tcp

18
推荐指数
1
解决办法
4648
查看次数

模拟在C#中撕掉一个双

我正在使用32位计算机运行,并且我能够使用以下快速命中的代码片段来确认长值可以撕裂.

        static void TestTearingLong()
        {
            System.Threading.Thread A = new System.Threading.Thread(ThreadA);
            A.Start();

            System.Threading.Thread B = new System.Threading.Thread(ThreadB);
            B.Start();
        }

        static ulong s_x;

        static void ThreadA()
        {
            int i = 0;
            while (true)
            {
                s_x = (i & 1) == 0 ? 0x0L : 0xaaaabbbbccccddddL;
                i++;
            }
        }

        static void ThreadB()
        {
            while (true)
            {
                ulong x = s_x;
                Debug.Assert(x == 0x0L || x == 0xaaaabbbbccccddddL);
            }
        }
Run Code Online (Sandbox Code Playgroud)

但是当我尝试与双打类似的东西时,我无法得到任何撕裂.有谁知道为什么?据我从规范中可以看出,只有浮点数的赋值才是原子的.分配给双人应该有撕裂的风险.

    static double s_x;

    static void TestTearingDouble()
    {
        System.Threading.Thread A = new System.Threading.Thread(ThreadA);
        A.Start(); …
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading double-precision atomicity

18
推荐指数
2
解决办法
789
查看次数

GC与C#和C++在同一解决方案中

我有一个由许多C#项目组成的解决方案.它是用C#编写的,以使其快速运行.垃圾收集开始成为一个问题 - 我们正在看到我们想要避免的100毫秒延迟.

一种想法是用C++重新编写它,逐个项目.但是,如果将C#与非托管C++结合使用,C++项目中的线程是否也会被垃圾收集冻结?

UPDATE

谢谢你的回复.事实上,这是一个100毫秒可能很重要的应用程序.在C#中构建它可能是一个糟糕的决定,但它必须在当时快速启动并运行.

现在,我们正在使用Windows的多媒体计时器每隔5毫秒触发一次事件.我们确实看到了100多个ms的间隙,我们通过检查GC计数器确认这些间隙总是在收集期间发生.优化正在进行; 内置于发布模式.

c# c++ multithreading garbage-collection

14
推荐指数
1
解决办法
1155
查看次数

同步VS. .NET中的异步套接字性能

我在.NET中读到的关于套接字的一切都说异步模式提供了更好的性能(特别是使用新的SocketAsyncEventArgs可以节省分配).

我认为如果我们谈论的是具有许多客户端连接的服务器,而不能为每个连接分配一个线程,这是有道理的.然后我可以看到使用ThreadPool线程并获得异步回调的优势.

但在我的应用程序中,我是客户端,我只需要通过一个tcp连接收听一个服务器发送市场价格数据.现在,我创建一个线程,将优先级设置为Highest,并使用它调用Socket.Receive().我的线程阻止此调用,并在新数据到达后唤醒.

如果我将其切换为异步模式,以便在有新数据时收到回调,我会看到两个问题

  1. 线程池线程将具有默认优先级,因此看起来它们将严格地比具有最高优先级的我自己的线程更糟糕.

  2. 我仍然需要在某个时刻通过单个线程发送所有内容.假设我几乎同时在N个不同的线程池线程上得到N个回调,通知我有新数据.它们提供的N字节数组无法在线程池线程上处理,因为无法保证它们代表N个唯一的市场数据消息,因为TCP是基于流的.我将不得不锁定并将字节放入数组中,并发出一些其他线程的信号,这些线程可以处理数组中的内容.所以我不确定N线程池线程是什么让我买.

我在想这个错吗?是否有理由在我的特定情况下使用Async模式连接到一个服务器的一个客户端?

更新:

所以我认为我误解了上面(2)中的异步模式.当有数据可用时,我会在一个工作线程上得到回调.然后我会开始另一个异步接收并获得另一个回调等.我不会同时得到N个回调.

但问题仍然是一样的.是否有任何理由在我特定的情况下回调会更好,我是客户端并且只连接到一台服务器.

.net c# sockets asynchronous tcp

10
推荐指数
1
解决办法
9710
查看次数

Proto2与C#中的Proto3

我必须使用proto2版本的Google Protocol Buffers向其他团队发送消息.他们在Linux上使用Java和C++.我在Windows上使用C#.

Jon Skeet的protobuf-csharp-port(https://github.com/jskeet/protobuf-csharp-port)支持proto2.如果我理解正确的话,谷歌已经采用了这段代码,并将其更新版本折叠到主要的protobuf项目中(https://github.com/google/protobuf/tree/master/csharp).但它不再支持C#的proto2,只支持proto3.

我不确定我应该使用哪个项目.似乎新的支持将更好(性能,如果其他团队升级则支持proto3).但我必须将我从proto2给出的.proto文件转换为proto3,并冒任何问题.

我已经读过,大多数情况下,proto2和proto3的消息是兼容的.我没有使用Protocol Buffers的经验,但我正在使用的.proto文件看起来非常香草,没有默认值或oneof或嵌套任何东西.所以我似乎可以删除他们的"必需"和"可选"关键字并使用新库,将其视为proto3文件.

在您看来,使用新的库是否值得麻烦?是否有原型功能列表会使proto2和proto3消息不兼容?

.net c# protocol-buffers

8
推荐指数
1
解决办法
9297
查看次数

.NET SortedDictionary但按值排序

我需要一个像a一样的数据结构,SortedDictionary<int, double>但是根据值而不是键来排序.当我们在字典中有大约3000个项目时,我需要大约1-2微秒来添加和删除项目.

我的第一个想法是简单地在我的代码中切换键和值.这几乎是有效的.通过这样做,我可以在测试中添加和删除元素大约1.2微秒.

但是键必须在SortedDictionary中是唯一的,这意味着我的逆字典中的值必须是唯一的.在某些情况下,他们可能不会.

.NET库中的某些想法已经对我有用吗?

.net c# collections dictionary sorteddictionary

6
推荐指数
1
解决办法
5891
查看次数

从C#调用非托管.dll的性能

使用以下语法从C#应用程序调用C++编写的.dll会增加多长时间?

[DllImport("abc.dll", EntryPoint = "xcFoo", CallingConvention = CallingConvention.Cdecl)]
public extern static Result Foo(out IntPtr session,
                [MarshalAs(UnmanagedType.FunctionPtr)]ObjectCallback callback, 
                UInt64 turnKey,
                string serverAddress, 
                string userId, 
                string password);
Run Code Online (Sandbox Code Playgroud)

有更有效的方法吗?

c# c++ interop unmanaged managed

5
推荐指数
1
解决办法
5248
查看次数

C#/ .NET中的二次规划

有谁知道一个免费的软件包可以解决C#中的二次编程问题?

我用Google搜索并发现了一些.但很难说哪个是最好和最快的.有没有人喜欢?

.net c# mathematical-optimization scientific-computing

5
推荐指数
1
解决办法
3219
查看次数