在使用Monitor.PulseAll()进行线程同步的库中,我注意到从PulseAll(...)被调用到线程被唤醒的时间的延迟似乎遵循"踩台阶"分布 - 极其大步.被唤醒的线程几乎没有工作; 并几乎立即回到监视器上等待.例如,在具有12个核心的盒子上,24个线程在监视器上等待(2x Xeon5680/Gulftown;每个处理器6个物理核心; HT禁用),Pulse和线程唤醒之间的延迟是这样的:
前12个线程(注意我们有12个内核)需要30到60微秒才能响应.然后我们开始获得非常大的跳跃; 高原在700,1300,1900和2600微秒左右.
我能够使用下面的代码成功地独立于第三方库重新创建此行为.这段代码的作用是启动大量线程(更改numThreads参数),只需在监视器上等待,读取时间戳,将其记录到ConcurrentSet,然后立即返回Waiting.一旦第二个PulseAll()唤醒所有线程.它执行此操作20次,并将第10次迭代的延迟报告给控制台.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
using System.Diagnostics;
namespace PulseAllTest
{
class Program
{
static long LastTimestamp;
static long Iteration;
static object SyncObj = new object();
static Stopwatch s = new Stopwatch();
static ConcurrentBag<Tuple<long, long>> IterationToTicks = new ConcurrentBag<Tuple<long, long>>();
static void Main(string[] args)
{
long numThreads = 32;
for (int i = 0; i < numThreads; ++i)
{
Task.Factory.StartNew(ReadLastTimestampAndPublish, TaskCreationOptions.LongRunning);
}
s.Start(); …
Run Code Online (Sandbox Code Playgroud) 我正在尝试创建一个接受Action和Timeout的函数,并在Timeout之后执行Action.该功能是非阻塞的.该函数必须是线程安全的.我也非常,真的想避免使用Thread.Sleep().
到目前为止,我能做的最好的是:
long currentKey = 0;
ConcurrentDictionary<long, Timer> timers = new ConcurrentDictionary<long, Timer>();
protected void Execute(Action action, int timeout_ms)
{
long currentKey = Interlocked.Increment(ref currentKey);
Timer t = new Timer(
(key) =>
{
action();
Timer lTimer;
if(timers.TryRemove((long)key, out lTimer))
{
lTimer.Dispose();
}
}, currentKey, Timeout.Infinite, Timeout.Infinite
);
timers[currentKey] = t;
t.Change(timeout_ms, Timeout.Infinite);
}
Run Code Online (Sandbox Code Playgroud)
问题是从回调本身调用Dispose()不是很好.我不确定"脱落"结束是否安全,即计时器在他们的lambdas执行时被认为是活的,但即使是这种情况,我宁愿妥善处理它.
"一次延迟起火"似乎是一个常见的问题,应该有一个简单的方法来做到这一点,可能是System.Threading中的其他一些库我想念,但是现在我能想到的唯一解决方案是修改上面有一个间隔运行的专用清理任务.有什么建议?
根据我的阅读,出于性能原因,某些集合的枚举器类型的设计决策是可变结构而不是引用类型.List.Enumerator是最知名的.
我正在研究一些使用数组的旧代码,并且惊讶地发现C#Arrays返回类型SZGenericArrayEnumerator作为它们的通用枚举器类型,它是一个引用类型.
我想知道是否有人知道为什么当许多其他性能关键集合使用可变结构时,Array的通用迭代器被实现为引用类型.
我目前正在尝试创建一个数据库,其中很大一部分数据是暂时的.在阅读了许多这样做的技术(大多数涉及6nf标准化)后,我遇到了锚点建模.
我正在开发的模式非常类似于Anchor Modeling模型,特别是因为用例(Temporal Data + Known Unknowns)是如此相似,我很想完全接受它.
我遇到的两个最大的问题是,我找不到任何详细说明这种方法的负面影响的内容,而且我找不到任何对生产中用于战争故事和陷阱的组织的引用,这些都是我需要注意的.
我想知道这里是否有人熟悉,可以简要地阐述一些否定因素(因为积极因素在研究论文及其网站上得到了很好的宣传),以及在生产环境中使用它的任何经验.
sql database-design temporal-database database-normalization anchor-modeling
我目前正在用C#编写一个应用程序,我需要大约启动一个计时器.每5毫秒.从一些研究看来,最好的方法是p /调用timeBeginPeriod(...)来改变系统计时器的分辨率.它在我的示例代码中运行良好.
我在此条目中发现了一条关于在Larry Osterman的MSDN博客上使用此功能的有趣警告:
Adam:调用timeBeginPeriod也可以提高GetTickCount的准确性.
使用timeBeginPeriod一般是一个非常糟糕的想法 - 我们一直在积极地删除它在Windows中的所有用途,因为使用它会带来功耗的后果.
有更好的方法可以确保您的线程及时运行.
有没有人确切知道为什么会发生这种情况,或者那些"更好的方式"(在线程中未指定)可能是什么?我们谈论的额外功耗是多少?
我试图比较三种不同的方式将委托传递给C#中的函数 - 由lambda,委托和直接引用.让我感到惊讶的是直接参考方法(即ComputeStringFunctionViaFunc(object[i].ToString))
比其他方法慢六倍.有谁知道为什么会这样?
完整代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.CompilerServices;
namespace FunctionInvocationTest
{
class Program
{
static void Main(string[] args)
{
object[] objectArray = new object[10000000];
for (int i = 0; i < objectArray.Length; ++i) { objectArray[i] = new object(); }
ComputeStringFunction(objectArray[0]);
ComputeStringFunctionViaFunc(objectArray[0].ToString);
ComputeStringFunctionViaFunc(delegate() { return objectArray[0].ToString(); });
ComputeStringFunctionViaFunc(() => objectArray[0].ToString());
System.Diagnostics.Stopwatch s = new System.Diagnostics.Stopwatch();
s.Start();
for (int i = 0; i < objectArray.Length; ++i)
{
ComputeStringFunction(objectArray[i]);
}
s.Stop();
Console.WriteLine(s.Elapsed.TotalMilliseconds);
s.Reset();
s.Start();
for …
Run Code Online (Sandbox Code Playgroud) 我正在尝试追踪与垃圾收集相关的性能问题,一个症状是"Promoted Finalization-Memory from Gen0"计数器显示了大量的对象,并且正在创建终结器并在完成Gen 0之后每个Gen0系列.
我怎样才能发现这些物体是什么?
我们有以下方法来测试我们的结构是否是POD.它总是返回true:
bool podTest() {
struct podTest {
int count;
int x[];
};
return std::is_pod<podTest>::value; //Always returns true
}
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.现在我们进行一次更改并删除复制构造函数:
bool podTest() {
struct podTest {
podTest(const podTest&) = delete;
int count;
int x[];
};
return std::is_pod<podTest>::value; //Always returns false
}
Run Code Online (Sandbox Code Playgroud)
这总是返回false.在阅读了is_pod
我的定义后,我仍在努力了解它违反了什么要求.我错过了什么?
这是使用gcc 6.1在godbolt上编译的 -std=c++14
我有一个非常简单的 CRTP 骨架结构,其中仅包含一个向量和基类中的一个私有访问器。CRTP 类中有一个辅助方法可以访问它。
#include <vector>
template<typename T>
class CRTPType {
// Will be used by other member functions. Note it's private,
// so declval/decltype expressions outside of friends or this class
// cannot see it
auto& _v() {
return static_cast<T *>(this)->getV();
}
};
class BaseType : public CRTPType<BaseType> {
friend class CRTPType<BaseType>;
std::vector<int> v;
//For different base types this impl will vary
auto& getV() { return v; }
};
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都很好。现在我想添加一个using
声明,CRTPType
该声明将是返回的类型_v()
。因此,理想情况下,人们可以执行如下操作:
template<typename T>
class …
Run Code Online (Sandbox Code Playgroud) 给定以下结构:
struct ExampleStruct {
char firstMember[8];
uint64_t secondMember;
};
Run Code Online (Sandbox Code Playgroud)
有没有办法写一个静态断言来验证偏移量secondMember
是8个字节的倍数?