posix和system v 信號量哪個更快?
posix命名信號量,書上說是將信息存入fifo文件中進行同步的,而system v信號量,是將信息存入內核。
按理來說,內核裡面的調用應該比fifo要快吧?為什麼我用兩種信號量,對同一種簡單的生產者消費者模型做測試,釋放和阻塞10000次,posix反而更快呢?
1. 你看的哪本書?2. 你在哪個系統下做的測試?代碼?
3. 為什麼要用信號量?
POSIX sem 實現是基於futex的。 在無競爭條件下,不需要陷入內核,執行系統調用,其實現是非常輕量級的。
System V sem 則不同,無論有無競爭都要執行系統調用,因此性能落了下風。 POSIX sem 由於沒有事事煩擾內核,所以內核也無法幫他記錄 sem_adj ,即POSIX sem 並沒有UNDO功能。@-@
Linux裡面,寫有限緩衝區生產者與消費者,生產者訪問10000000*2,消費者訪問10000000*2,用POSIX實現共享內存互斥和用系統V實現進行比較,前者運行時間是後者的1/4。。。
我用系統V做還以為死循環了。。。被坑死啦QAQThe Linux Programming Interface 53.5 Comparisons with Other Synchronization Techniques提到POSIX和SYSV兩種版本的semaphore,有競爭的時候POSIX版本會快一些
glibc的實現(nptl/sysdeps/unix/sysv/linux/sem_{wait,post}.c nptl/sysdeps/unix/sysv/linux/sem_wait.c),semop是系統調用的wrapper;而無競爭的時候sem_{wait,post}只需要原子操作,沒有系統調用,因此可能會快些。
#define _DEFAULT_SOURCE 1
#include &
#include &
#include &
#include &
#include &
#include &
#include &
#define REP(i, n) FOR(i, 0, n)
#define FOR(i, a, b) for (int i = (a); i &< (b); i++)
#define N 10000000
sem_t *sem;
int semid;
struct sembuf sop1, sop2;
void *posix1(void *arg)
{
REP(i,N)
if (sem_wait(sem) &< 0)
err(1, "sem_wait");
return NULL;
}
void *posix2(void *arg)
{
REP(i,N)
if (sem_post(sem) &< 0)
err(1, "sem_post");
return NULL;
}
void *sysv1(void *arg)
{
REP(i,N)
if (semop(semid, sop1, 1) &< 0)
err(1, "semop");
return NULL;
}
void *sysv2(void *arg)
{
REP(i,N)
if (semop(semid, sop2, 1) &< 0) // may fail if the value exceeds semvmx
err(1, "semop");
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t pid1, pid2;
if (! argv[1]) {
puts("posix");
if ((sem = sem_open("/meow", O_CREAT, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED)
err(1, "sem_open");
if (pthread_create(pid1, NULL, posix1, NULL))
errx(1, "pthread_create");
if (pthread_create(pid2, NULL, posix2, NULL))
errx(1, "pthread_create");
} else {
puts("sysv");
if ((semid = semget(IPC_PRIVATE, 1, IPC_CREAT | S_IRWXU)) &< 0)
err(1, "semget");
sop1.sem_op = -1;
sop1.sem_num = 0;
sop1.sem_flg = 0;
sop2.sem_op = 1;
sop2.sem_num = 0;
sop2.sem_flg = 0;
if (pthread_create(pid1, NULL, sysv1, NULL))
errx(1, "pthread_create");
if (pthread_create(pid2, NULL, sysv2, NULL))
errx(1, "pthread_create");
}
if (pthread_join(pid1, NULL) || pthread_join(pid2, NULL))
errx(1, "pthread_join");
if (! argv[1]) {
if (sem_close(sem) &< 0)
err(1, "sem_close");
} else {
if (semctl(semid, 0, IPC_RMID) &< 0)
err(1, "semctl");
}
return 0;
}
都很慢,多線程是個不好的設計,能不用盡量別用
推薦閱讀:
※同為開源的類unix系統,為什麼FreeBSD遠沒有Linux流行?
※除了Windows和UNIX內核兩大桌面操作系統外,歷史上是否曾出現其他具有一定實用價值的操作系統?
※Linux 算不算是 UNIX 的一個分支?
※Atom, Vim, Visual Studio Code, Emacs 哪個好?
※C的結構體成員變數的命名有必要加前綴嗎?