我正在使用arm imx27板在Windows CE和Linux之间进行性能评估。代码已经为CE编写并测量了执行不同内核调用所需的时间,例如使用互操作和信号量等操作系统原语,打开和关闭文件以及联网。
在我将此应用程序移植到Linux(pthreads)期间,我偶然发现了一个我无法解释的问题。几乎所有测试都显示性能提高了5到10倍,但不是我的win32 events版本SetEvent
和WaitForSingleObject
),CE实际上“赢了”了这个测试。
要模仿我使用pthreads条件变量的行为(我知道我的实现并没有完全模拟CE版本,但它足以进行评估)。
测试代码使用两个使用事件互相“ping-pong”的线程。
主题1:(我测量的主题)
HANDLE hEvt1, hEvt2;
hEvt1 = CreateEvent(NULL, FALSE, FALSE, TEXT("MyLocEvt1"));
hEvt2 = CreateEvent(NULL, FALSE, FALSE, TEXT("MyLocEvt2"));
ResetEvent(hEvt1);
ResetEvent(hEvt2);
for (i = 0; i < 10000; i++)
{
SetEvent (hEvt1);
WaitForSingleObject(hEvt2, INFINITE);
}
主题2:(只是“回复”)
while (1)
{
WaitForSingleObject(hEvt1, INFINITE);
SetEvent(hEvt2);
}
主题1:(我测量的主题)
struct event_flag *event1, *event2;
event1 = eventflag_create();
event2 = eventflag_create();
for (i = 0; i < 10000; i++)
{
eventflag_set(event1);
eventflag_wait(event2);
}
主题2:(只是“回复”)
while (1)
{
eventflag_wait(event1);
eventflag_set(event2);
}
我对eventflag_*
的实施:
struct event_flag* eventflag_create()
{
struct event_flag* ev;
ev = (struct event_flag*) malloc(sizeof(struct event_flag));
pthread_mutex_init(&ev->mutex, NULL);
pthread_cond_init(&ev->condition, NULL);
ev->flag = 0;
return ev;
}
void eventflag_wait(struct event_flag* ev)
{
pthread_mutex_lock(&ev->mutex);
while (!ev->flag)
pthread_cond_wait(&ev->condition, &ev->mutex);
ev->flag = 0;
pthread_mutex_unlock(&ev->mutex);
}
void eventflag_set(struct event_flag* ev)
{
pthread_mutex_lock(&ev->mutex);
ev->flag = 1;
pthread_cond_signal(&ev->condition);
pthread_mutex_unlock(&ev->mutex);
}
struct
:
struct event_flag
{
pthread_mutex_t mutex;
pthread_cond_t condition;
unsigned int flag;
};
答案 0 :(得分:3)
请注意,在调用pthread_cond_signal()
时不需要持有互斥锁,因此您可以通过在发出条件信号之前释放互斥锁来提高条件变量'event'实现的性能:< / p>
void eventflag_set(struct event_flag* ev)
{
pthread_mutex_lock(&ev->mutex);
ev->flag = 1;
pthread_mutex_unlock(&ev->mutex);
pthread_cond_signal(&ev->condition);
}
这可能会阻止唤醒的线程立即阻塞互斥锁。
答案 1 :(得分:0)
这种类型的实施仅在您能够错过活动时才有效。我刚测试它并遇到了很多死锁。这样做的主要原因是条件变量只唤醒已经在等待的线程。之前发出的信号丢失了。
如果条件已经发出信号,则没有计数器与允许等待线程简单地继续的条件相关联。 Windows事件支持此类用法。
我认为没有比使用信号量(POSIX版本非常易于使用)更好的解决方案,初始化为零,使用sem_post()
set()
和sem_wait()
{ {1}}。您肯定可以想到一种方法,使用wait()
那说我不知道POSIX信号量是否只是Linux信号量的简洁接口或性能损失是什么。