Hi, Problem Statement Our application uses System V semaphore extensively. We are facing performance issue with it.
Problem Description We have created a sample code (attached with name shm_sem.cpp) which uses System V shared memory and semaphore. This code takes semaphore lock, updates the shared memory and unlock semaphore. It is done in a loop for 50k times. It takes around 21 seconds to complete. We have compiled and executed the same code on Linux which completes instantly. Following is the outcome of run from Cygwin and REHL 7.9 Linux VM: Cygwin: uname -a CYGWIN_NT-10.0-17763 Win19Build01 3.5.3-1.x86_64 2024-04-03 17:25 UTC x86_64 Cygwin Compiled with : g++ -o shm_sem shm_sem.cpp shm_sem.exe 2024-09-04 01:23:44.505687 => Starting... 2024-09-04 01:24:05.500330 => Finished... 2024-09-04 01:24:05.500989 => Shared memory and semaphore cleaned up. RHEL Linux: uname -a Linux Linux6BuildDev03 3.10.0-1160.59.1.el7.x86_64 #1 SMP Wed Feb 16 12:17:35 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux Compiled with : g++ -o shm_sem shm_sem.cpp ./shm_sem 2024-09-04 08:22:16.302955 => Starting... 2024-09-04 08:22:16.385529 => Finished... 2024-09-04 08:22:16.385631 => Shared memory and semaphore cleaned up. Is this expected behavior or there are any configuration or any changes you can suggest which might improve its performance will be very helpful. Attachments: 1. Sample code : shm_sem.cpp 1. Cygserver config file: cygserver.conf 1. Cygcheck output (cygcheck -s -v -r > cygcheck.out): cygcheck.out Thanks Abinash Mohanty
/* System V Semaphore */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <sys/types.h> #include <sys/time.h> #include <time.h> #include <unistd.h> #include <errno.h> #define SHM_SIZE 1024 // Shared memory size #define SEM_KEY 0x1234 // Semaphore key #define SHM_KEY 0x5678 // Shared memory key // Union required for semctl union semun { int val; // value for SETVAL struct semid_ds *buf; // buffer for IPC_STAT, IPC_SET unsigned short *array; // array for GETALL, SETALL }; void error(const char *msg) { perror(msg); exit(1); } void log_write(const char *format, ...) { va_list args; int count; char buf[1024]; struct timeval tval; struct tm lt; char time_stamp[100]; gettimeofday(&tval, NULL); localtime_r(&tval.tv_sec, <); sprintf(time_stamp, "\n%04d-%02d-%02d %02d:%02d:%02d.%06d", lt.tm_year+1900, lt.tm_mon+1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec, (int)tval.tv_usec); va_start( args, format ); count = vsprintf( buf, format, args); va_end( args ); if ( buf[strlen(buf)-1] == '\n' ) buf[strlen(buf)-1] = 0; printf( "%s => %s", time_stamp, buf); } int sem_block(int sem_id,int sem_num) { struct sembuf sops; sops.sem_num = sem_num; sops.sem_op = -1; sops.sem_flg = SEM_UNDO; if (semop(sem_id, (struct sembuf *)&sops,1) == -1) { if (errno != EINTR) error ("sem_block: semop error\n"); return(-1); } return(0); } int sem_clear(int sem_id,int sem_num) { struct sembuf sops; sops.sem_num = sem_num; sops.sem_op = 1; sops.sem_flg = SEM_UNDO; if (semop(sem_id, (struct sembuf *)&sops,1) == -1) { if (errno != EINTR) error ("sem_clear: semop error\n"); return(-1); } return(0); } void sem_enter (int sem_id, int sem_num) { int rv; do { rv = sem_block(sem_id,sem_num); } while (rv == -1 && errno == EINTR); if (rv == -1) error ("que_enter: sem_block error\n"); } void sem_leave (int sem_id, int sem_num) { int rv; do { rv = sem_clear(sem_id,sem_num); } while (rv == -1 && errno == EINTR); if (rv == -1) error ("que_leave: sem_clear error\n"); } int main() { int shm_id, sem_id; void *shm_ptr; int nsems = 1; // Create shared memory shm_id = shmget(SHM_KEY, SHM_SIZE, 0644 | IPC_CREAT | IPC_EXCL); if (shm_id == -1) error("shmget"); // Attach shared memory shm_ptr = shmat(shm_id, NULL, 0); if (shm_ptr == (void *)-1) error("shmat"); // Create semaphore sem_id = semget(SEM_KEY, nsems, 0666 | IPC_CREAT|IPC_EXCL); if (sem_id == -1) error("semget"); // Initialize semaphore to 1 (unlocked state) union semun sem_union; sem_union.val = 1; for ( int i = 0; i < nsems; i++ ) { if (semctl(sem_id, i, SETVAL, sem_union) == -1) error("semctl SETVAL"); } log_write("Starting...\n"); int num_out = 0; for (int num_in = 1; num_in <= 50000; num_in++ ) { // Semaphore lock sem_enter(sem_id, 0); // Write to shared memory memcpy(shm_ptr, &num_in, sizeof(int)); // Semaphore unlock sem_leave(sem_id, 0); } log_write("Finished...\n"); // Cleanup // Detach shared memory if (shmdt(shm_ptr) == -1) error("shmdt"); // Remove shared memory if (shmctl(shm_id, IPC_RMID, NULL) == -1) error("shmctl"); // Remove semaphore if (semctl(sem_id, 0, IPC_RMID, sem_union) == -1) error("semctl IPC_RMID"); log_write("Shared memory and semaphore cleaned up.\n"); return 0; }
cygcheck.out
Description: cygcheck.out
cygserver.conf
Description: cygserver.conf