Une différence potentiellement significative pourrait être l'équité de la distribution des ressources. Je ne connais pas les détails de la mise en œuvre de la famille semget/semop
, mais je soupçonne qu'elle est généralement implémentée comme un sémaphore "traditionnel" en ce qui concerne la planification. Généralement, je crois que les threads libérés sont gérés sur une base FIFO (le premier qui attend le sémaphore est libéré en premier).Je ne pense pas que cela se produirait avec le verrouillage de fichier car je suspecte (encore une fois de deviner) que la manipulation n'est pas effectuée au niveau du noyau. J'ai eu du code existant assis pour tester les sémaphores à des fins IPC, et j'ai donc comparé les deux situations (une utilisant semop
et une utilisant lockf
). J'ai fait un test d'un pauvre et j'ai juste couru à des instances de l'application. Le sémaphore partagé a été utilisé pour synchroniser le début. Lors de l'exécution du test semop, les deux processus ont terminé 3 millions de boucles presque synchronisées. La boucle de verrouillage, d'autre part, n'était pas aussi juste. Un processus se termine généralement alors que l'autre n'a complété que la moitié des boucles.
La boucle du test semop ressemblait à ceci. Les fonctions semwait
et semsignal
ne sont que des wrappers pour les appels semop
.
ct = myclock();
for (i = 0; i < loops; i++)
{
ret = semwait("test", semid, 0);
if (ret < 0) { perror("semwait"); break; }
if ((i & 0x7f) == 0x7f)
printf("\r%d%%", (int)(i * 100.0/loops));
ret = semsignal(semid, 0);
if (ret < 0) { perror("semsignal"); break; }
}
printf("\nsemop time: %d ms\n", myclock() - ct);
Le temps d'exécution total pour les deux méthodes était à peu près la même, bien que la version lockf était en fait parfois globalement plus rapide en raison de l'iniquité de la programmation. Une fois le premier processus terminé, l'autre processus aurait un accès incontesté pour environ 1,5 million d'itérations et serait extrêmement rapide.
Lors de l'exécution non contestée (processus unique obtenant et libérant les verrous), la version semop était plus rapide. Il a fallu environ 2 secondes pour 1 million d'itérations tandis que la version lockf a pris environ 3 secondes.
Cela a été exécuté sur la version suivante:
[]$ uname -r
2.6.11-1.1369_FC4smp
Je me souviens que pthread_mutex_t dans une mémoire partagée rend parfois du mal, si je me souviens bien sur du noyau 2.4.x. Connaissez-vous quelque chose à ce sujet? – DarkDust
@DarkDust: versions du noyau antérieures à 2.6.quelque chose (mais il y a de nombreuses années) avait une implémentation pthread différente, qui n'était en fait pas adaptée au contrôle interprocessus. C'est l'histoire. Quoi qu'il en soit, l'appel 'init' correspondant vous indiquera au retour si l'attribut' pshared' n'est pas supporté par l'implémentation. –
Vous sacrifiez la portabilité avec cette technique? – bstpierre