我读过很多关于volatile和VoletileRead(ReadAcquireFence)的矛盾信息(msdn,SO等).
我理解那些内存访问重新排序的限制含义 - 我仍然完全混淆的是新鲜度保证 - 这对我来说非常重要.
(...)这可确保始终在字段中显示最新值.
读取volatile字段称为volatile读取.易失性读取具有"获取语义"; 也就是说,保证在指令序列之后发生的任何内存引用之前发生.
public static int VolatileRead(ref int address)
{
int ret = address;
MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
return ret;
}
Run Code Online (Sandbox Code Playgroud)
根据msdn MemoryBarrier doc内存屏障阻止重新排序.然而,这似乎对新鲜度没有任何影响 - 对吗?
如何获得新鲜度保证?标记字段volatile与使用VolatileRead和VolatileWrite语义访问它之间有区别吗?我目前正在执行我的性能关键代码,需要保证新鲜度,但读者有时会得到陈旧的价值.我想知道是否标记状态不稳定将使情况不同.
EDIT1:
我正在努力实现的目标 - 保证读者线程将尽可能获得共享变量(由多个编写者编写)的最新值 - 理想情况下不会超过上下文切换或其他可能推迟立即操作的操作的成本写国家.
如果挥发性或更高级别的构造(例如锁定)具有这种保证(是吗?)而不是它们如何实现这一点?
EDIT2:
非常简洁的问题应该是 - 如何在读取过程中尽可能保证新的价值?理想情况下没有锁定(因为不需要独占访问,并且存在高争用的可能性).
从我在这里学到的东西,我想知道这可能是解决方案(求解(?)行标有注释):
private SharedState _sharedState;
private SpinLock _spinLock = new SpinLock(false);
public void Update(SharedState newValue) …Run Code Online (Sandbox Code Playgroud) 简化问题:
与内存屏障相比,互锁操作引起的内存缓存一致性(或"刷新")的时间是否存在差异?让我们在C#中考虑 - 任何互锁操作与Thread.MemoryBarrier().我相信存在差异.
背景:
我读了很少关于内存障碍的信息 - 所有对预防特定类型的内存交互指令重新排序的影响,但是我找不到关于它们是否应该立即刷新读/写队列的一致信息.
实际上我发现很少有消息来源提到不能保证操作的即时性(只保证特定的重新排序是有保证的).例如
维基百科:"但是,要明确的是,这并不意味着任何操作都会在屏障完成时完成;只有完成操作的订购(当它们完成时)才能得到保证"
Freebsd.org(障碍是硬件特定的,所以我猜一个特定的操作系统并不重要):"内存屏障只是确定内存操作的相对顺序;它们不保证内存操作的时间"
另一方面,Interlocked操作 - 从他们的定义 - 导致立即刷新所有内存缓冲区以保证更新的最新值更新导致内存子系统用值锁定整个缓存行,以防止从任何访问(包括读取)其他CPU /核心,直到操作完成.
我纠正还是错了?
免责声明:
这是我在这里的原始问题的演变.在.NET中的可变新鲜度保证(易失性与易失性读取)
EDIT1: 修复了关于Interlocked操作的声明 - 内联文本.
编辑2: 完全删除演示代码+它的讨论(因为一些人抱怨太多的信息)
问题:System.Threading.Timer尽管OS时钟分辨率更精确,
为什么保持15ms的分辨率?在没有繁忙的CPU等待的情况下,实现1ms定时事件分辨率的可行方法是什么?
再次强调:在我的情况下,系统计时器的分辨率为1ms(而不是建议重复的问题).所以这不是系统计时器分辨率的问题.因此,在所谓的重复问题中没有有用的信息.
背景:
.NET似乎System.Threading.Timer 没有使用系统时钟分辨率 - 它保持了~15ms的分辨率.尽管OS时钟(例如Sleep分辨率)更加精确.
在我的盒子上(当几乎空闲且4个核心可用时):
>Clockres.exe
ClockRes v2.0 - View the system clock resolution
Copyright (C) 2009 Mark Russinovich
SysInternals - www.sysinternals.com
Maximum timer interval: 15.625 ms
Minimum timer interval: 0.500 ms
Current timer interval: 1.001 ms
Run Code Online (Sandbox Code Playgroud)
输出我的快速测试:
Sleep test:
Average time delta: 2[ms] (from 993 cases)
System.Threading.Timer test:
Average time delta: 15[ms] (from 985 cases)
Run Code Online (Sandbox Code Playgroud)
测试代码是:
private static void TestSleepVsTimer(long millisecondsDifference, int repetions)
{
TimingEventsKeeper timingEventsKeeper …Run Code Online (Sandbox Code Playgroud) 我需要对MemoryMappedFile.NET 中的内存使用Interlocked Operations(CompareExchange,Increment等).
我找到了一个非常相似的问题的答案.问题是Interlocked Operations不是从64位操作系统上的kernel32(或任何其他)dll导出的(参见例如http://blog.kalmbachnet.de/?postid=46).
有没有其他方法可以在64位.NET进程中调用内存块上的互锁函数?
在.NET 4.6下,Ngen和RyuJIT是两个完全不相关的东西(特别是使用不同的优化技术和算法)?
如果我们不关心自身抖动和/或冷/热启动时间的成本,那么什么产生最快(更好的优化)x64本机代码?
我们正在运行一个长期运行的服务器应用 连续运行阶段在性能方面非常重要.(预)启动阶段对我们来说并不重要.到目前为止,我们已经使用.NET 4.5并且始终由Ngen生成本机映像.我们现在正在升级到.NET 4.6,我们希望确保这不会降低我们持续运行阶段的性能.我已经阅读了一些信息,RyuJIT是改善JITing时间的绝佳选择,但是与Ngen相比,jited代码可能没有那么优化 - 参见例如关于其中一个RyuJIT错误的github评论.
我们有两个代码片段:
A:
public class Foo
{
private static Bar _unused = new Bar();
}
Run Code Online (Sandbox Code Playgroud)
B:
public class Foo
{
private static Bar _unused;
static Foo()
{
_unused = new Bar();
}
}
Run Code Online (Sandbox Code Playgroud)
在情况A中,CLR甚至不会调用Bar ctor(除非它是调试版本或附加调试器),但是在情况B中它在所有情况下都被调用.
问题是,在Bar构造函数中,可以进行调用,使其可以从其他地方访问 - 最常见的是事件订阅.
所以:
为了全局配置最小RTO; 延迟Ack超时; Windows 7及以上版本的拥塞算法等应该使用网络TCP模板.要查看那些可以使用Get-NetTCPSetting powershell cmdlet:
PS C:\Users\Administrator> Get-NetTCPSetting
(...)
SettingName : Datacenter
MinRto(ms) : 20
InitialCongestionWindow(MSS) : 4
CongestionProvider : DCTCP
CwndRestart : True
DelayedAckTimeout(ms) : 10
MemoryPressureProtection : Enabled
AutoTuningLevelLocal : Normal
AutoTuningLevelGroupPolicy : NotConfigured
AutoTuningLevelEffective : Local
EcnCapability : Enabled
Timestamps : Disabled
InitialRto(ms) : 3000
ScalingHeuristics : Disabled
DynamicPortRangeStartPort : 49152
DynamicPortRangeNumberOfPorts : 16384
SettingName : Internet
MinRto(ms) : 300
InitialCongestionWindow(MSS) : 4
CongestionProvider : CTCP
CwndRestart : False
DelayedAckTimeout(ms) : 50
MemoryPressureProtection : Enabled
AutoTuningLevelLocal …Run Code Online (Sandbox Code Playgroud) 我们需要在 .NET 中以编程方式创建巨大的 zip 文件。目前我们使用STL System.IO.Compression.ZipFile.CreateFromDirectory函数,该函数效果很好,但是当目标归档文件大于4GB时,所有归档工具(包括内置的windows zip支持)都无法正确打开它并认为它是已损坏。我也尝试了相当多的支持 zip64 格式的工具(7zip、TUGZip、DotNetZip 库等),但他们也认为它已损坏。
我仍然可以使用 System.IO. Compression.ZipFile.ExtractToDirectory 函数来提取它。不过,我想避免重新发明轮子并编写自己的工具来从存档中提取选定的文件(每次只需要 1 个日志时都完全提取它是不可接受的)
您是否知道任何(最好是免费的)工具可以打开由 ZipFile.CreateFromDirectory 创建的大于 4GB 的 zip 存档?或者甚至是使用 ZipFile.ExtractToDirectory 非常简单地提取所选文件的现有代码片段。
我需要在一台机器上实现非常快速,低延迟,高吞吐量的进程间(或应用程序间)通信.
消息通常每隔几毫秒流动一次(但在几分钟内,每毫秒甚至可能有多达3-5条消息),每条消息大约不到1KB,目标往返延迟最大为1ms(通过往返我的意思是交付一条消息,然后以某种方式回叫生产者,以宣布消费者是否想要"声明"该消息).
我做了一些研究,似乎内存映射文件是最快的可能性,但我需要专有实现它周围的整个通信堆栈(共享内存的分配和管理,将消息复制到其中并从中复制消息并向消费者发信号通知新消息已准备好被消费).我在Windows上看到了显示IPC方法体系结构的图片(http://blogs.msdn.com/b/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files-in-net-4 .aspx)似乎这些方法已经使用了MMF.所以通过我所描述的 - 我不会通过重新实现Named Pipes已经做的事情来重新发明轮子.或者我实际上可以实现比命名管道提供的协议快得多的协议?
编辑1:将frgotten链接添加到图片,显示命名管道建立在MMF之上(http://blogs.msdn.com/b/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files- in-net-4.aspx)
我在负载测试场景下遇到了奇怪的行为:后端(sql server 2012)正在超载并且一些命令超时(这仍然是预期的,因为后端服务器是半故意慢的HW); 但我们的平台定期(越来越延迟)重试超时操作 - 并在几次重试后突然开始接收'无法插入重复键'SqlException.
我验证只能生成具有特定唯一键的单行并尝试插入(第一次插入并且所有可能的重试始终在同一线程上进行).
我还修改了SP,以便它使用显式事务:
BEGIN TRY
BEGIN TRANSACTION;
-- Insert into table A
-- Insert into table B
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
THROW
END CATCH
Run Code Online (Sandbox Code Playgroud)
但问题仍然存在.
有什么想法可以发生这种情况吗?
如何找出超时的来源(后端与客户端)?
有没有办法确保操作成功完成或失败(基本上是事务 - 但可能来自客户端代码)?
EDIT01: 我认为解决这个问题的一种方法是利用ado.net集成SQL服务器分布式事务 - 例如:
using (TransactionScope scope = new TransactionScope())
{
//Perform the sql commands
//if above statements throws (e.g. due to timeout) - than the transaction is not commited and it will be rolled back
scope.Complete()
}
Run Code Online (Sandbox Code Playgroud)
但是:我同意它只会增加复杂性并且可能仍然反对同一个问题(usr概述的两个将军问题).因此,最好的方法可能是编写客户端和服务器端的代码来依赖这样的选项 - 再次由usr在他的回答中指出
是否有任何现有工具能够在保留提交哈希的情况下将Merurial存储库导出到git存储库?
我知道hg-git或fast-export.git,但是它们使用新的哈希创建新的提交(而且似乎没有任何选项可以配置它)。我们在Bitbucket上托管了数百个Mercurial存储库,其中包含大量的挂钩,下载链接等,具体取决于确切的哈希值。能够保留哈希值将为我们节省更新所有外部资源所需的大量工作。
我正在使用 hggit 将我们的 mercurial 存储库导出到 git。我正在关注这里的教程:http : //arr.gr/blog/2011/10/bitbucket-converting-hg-repositories-to-git/ 但是这会错过所有未合并到默认值的分支。我想这是因为单个书签(hg bookmark -r default master)。我是否需要分别为每个开放的分支添加书签?hggit 能否以某种方式选择所有打开的分支(因为我们可能有很多分支)?
c# ×8
.net ×7
git ×2
hg-git ×2
interlocked ×2
mercurial ×2
ado.net ×1
bitbucket ×1
compression ×1
ipc ×1
jit ×1
named-pipes ×1
networking ×1
ngen ×1
optimization ×1
ryujit ×1
scheduling ×1
sql-server ×1
tcp ×1
timer ×1
volatile ×1
windows ×1
zip ×1