Lock non bloquant versus lock bloquant ?

Discussion dans 'Développement d'un site Web ou d'une appli mobile' créé par ortolojf, 22 Juin 2021.

  1. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    3 456
    J'aime reçus:
    27
    Bonjour

    C'est pour la classe class_cache.inc.php de cache html de noren, et aussi pour mon site web.

    Je cherche à faire une classe de gestion d'accès à une ressource en lecture/écriture, de telle manière que, si le fichier/ressource existe, on y accède en lecture, sinon le processus est censé écrire dedans, sans que d'autres processus ne puissent écrire en même temps.

    J'hésite entre un lock bloquant et un lock non bloquant.

    PHP ne permet pas théoriquement, les locks non bloquants, du moins de savoir si la ressource est disponible ou non, d'une manière suffisamment atomistique, avant le lock.

    Mais, sur le PHP Manual, il y a cette classe ci-dessous ( transformée en classe par mes soins ).

    Quelle est a meilleure solution, du point de vue rapidité ? Bloquant ou non bloquant ?

    Pour le cache, la durée de la tâche est celle du chargement de la page.

    Pour le reste, c'est un peu plus court

    Merci beaucoup pour vos réponses.

    Amicalement.


    PHP:

    <?php

    class Semaphore_non_blocking {
            const 
    SHARED_MEMORY 100;
            public 
    $fp_log                null;
            private 
    $projectId            null;
            private 
    $resourceSemaphore    null;
            private 
    $tokenSemaphore        null;
            private 
    $tokenValue            null;
            private 
    $resourceSemaphoreKey    null;
            private 
    $tokenSemaphoreKey        null;
            private 
    $tokenValueKey            null;
            public function 
    __construct($filename$is_cache false) {
                if(
    $is_cache === false) {
                    
    $this->projectId    "aplusbegalix";
                } else {
                    
    $this->projectId    "abraracourcix";
                }
                
    $var $filename "_" $this->projectId;
                
    /**
                    $this->fp_log = fopen(basename($filename) . ".log", "w+");
                    if($this->fp_log === false) {
                            echo "failed to open : " . $filename . ".log" . "<br />\n";
                            return false;
                    }
                    **/
                    
    $this->resourceSemaphoreKey    = (int)preg_replace("/[^0-9]/","",(preg_replace("/[^0-9]/","",md5($var))/35676248)/619876); // text to number system.
                    
    $this->tokenSemaphoreKey    $this->resourceSemaphoreKey 1387655434;
                    
    $this->tokenValueKey        $this->resourceSemaphoreKey 2386421167;
                    
    $tmp_array = array('$this->resourceSemaphoreKey' => $this->resourceSemaphoreKey,
                            
    '$this->tokenSemaphoreKey' => $this->tokenSemaphoreKey,
                            
    '$this->tokenValueKey' => $this->tokenValueKey);
                    
    //    $this->myEcho(var_export($tmp_array, true));
                    
    if(($this->resourceSemaphoreKey    == -1) ||
                            (
    $this->tokenSemaphoreKey == -1) ||
                            (
    $this->tokenValueKey == -1)) {
                            echo 
    "failed to get key of semaphore. <nbr />\n";
                            return 
    false;
                    }
                    
    $this->resourceSemaphore sem_get($this->resourceSemaphoreKey10666true);
                    
    $this->tokenSemaphore sem_get($this->tokenSemaphoreKey10666true);
                    
    $this->tokenValue shm_attach($this->tokenValueKeyself::SHARED_MEMORY0666);
                    if((
    $this->resourceSemaphore === false) ||
                            (
    $this->tokenSemaphore === false) ||
                            (
    $this->tokenValue === false)) {
                            echo 
    "failed to get semaphore. <nbr />\n";
                            return 
    false;
                    }
                    
    $this->LOCK();
                    return 
    $this;
            }
            public function 
    __destruct() {
                    
    $this->UNLOCK();
    //                fclose($this->fp_log);
                    
    @shm_remove($this->tokenValue);
                    @
    shm_detach($this->tokenValue);
                    @
    sem_remove($this->tokenSemaphore);
                    @
    sem_remove($this->resourceSemaphore);
            }
            private function 
    myEcho($v) {
    //            echo  microtime() . ' ' . $v . "\n";
    //            fputs($this->fp_log, microtime() . ' ' . $v . "\n");
            
    }
            public function 
    try_lock() {
                    
    //    $this->myEcho('begin try_lock()');
                    //    $this->myEcho('acquire token semaphore');
                    
    sem_acquire($this->tokenSemaphore);
                    
    //    $this->myEcho('    token semaphore acquired');
                    
    $tmp = @shm_get_var($this->tokenValue$this->tokenValueKey);
                    
    //    $this->myEcho('    token value: ' . var_export($tmp, true));
                    
    $exit $tmp;
                    if (!
    $exit) {
                            
    $tmp = @shm_put_var($this->tokenValue$this->tokenValueKeytrue);
                            
    $tmp = @shm_get_var($this->tokenValue$this->tokenValueKey);
                            
    //    $this->myEcho('    token new value: ' . var_export($tmp, true));
                    
    }
                    
    //    $this->myEcho('release token semaphore');
                    
    sem_release($this->tokenSemaphore);
                    if (
    $exit) return false;
                    
    //    $this->myEcho('acquire resource semaphore');
                    
    sem_acquire($this->resourceSemaphore);
                    
    //    $this->myEcho('    resource semaphore acquired');
                    
    return true;
            }
            private function 
    release() {
                    
    //    $this->myEcho('release resource semaphore');
                    
    sem_release($this->resourceSemaphore);
                    
    //    $this->myEcho('acquire token semaphore');
                    
    sem_acquire($this->tokenSemaphore);
                    
    //    $this->myEcho('    token semaphore acquired');
                    
    $tmp = @shm_get_var($this->tokenValue$this->tokenValueKey);
                    
    //    $this->myEcho('    token value: ' . var_export($tmp, true));
                    
    $tmp = @shm_put_var($this->tokenValue$this->tokenValueKeyfalse);
                    
    $tmp = @shm_get_var($this->tokenValue$this->tokenValueKey);
                    
    //    $this->myEcho('    token new value: ' . var_export($tmp, true));
                    //    $this->myEcho('release token semaphore');
                    
    sem_release($this->tokenSemaphore);
            }
            private function 
    LOCK() {
                    for (
    $triesLeft 5$triesLeft && !$this->try_lock(); $triesLeft--) {
                            
    //    $this->myEcho('failed to acquire resource');
                            //    $this->myEcho('wait for 1 sec');
                            
    usleep(1000);
                            
    //    $this->myEcho('try again');
                    
    }
                    
    //paste here your code, accessing your resource
    //                $this->release();
            
    }
            private function 
    UNLOCK() {
                    
    $this->release();
            }
    }
    ?>

     
  2. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    3 456
    J'aime reçus:
    27
    Rebonjour

    A propos des mémoires partagées :

    Mon nombre max de segments est : 1024.

    Celà veut-il dire que je n'ai le droit de faire 1024 shm_attach() maximum ?

    Dans ce cas, comment augmenter 1024 ?

    Chaque shm occupe théoriquement 100 octets.

    J'ai fait un "ramasse-miettes" des mémoires partagées, ne supprimant que les shm créés par Nginx.

    Est-il envisageable, de lancer ce ramasse-miette par crontab régulièrement, en laissant les shm au lieu de les supprimer avec shm_remove() dans le destructeur de mon script ci-dessus ?

    Ces suppressions n'entraînent-ils pas des erreurs dans mon script ?

    Merci beaucoup.
     
  3. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    3 456
    J'aime reçus:
    27
    Excusez-moi

    J'ai l'intention de tweaker mes variables shm de configuration dans /etc/sysctl.conf.

    J'aurais besoin de savoir leurs significations.

    Voici ci-dessous un exemple de config pour mes 8 Go de RAM ( VPS de OVH ).

    Est-ce que des valeurs trop élevées de kernel.shmmni seraient gênantes ?

    kernel.shmseg peut rester à 4096.

    Merci beaucoup de vos réponses


    Code:
    
        RAM = 8 * (1024 ** 3)
    
        PAGE_SIZE     => 4096
    
        kernel.shmmax = RAM / 2.    //    maximum size of a shared memory segment (in pages)
        kernel.shmmax = RAM / 2 = (kernel.shmall*PAGE_SIZE)
    
        kernel.shmmin: 1            //    minimum size    of a shared memory segment  (in bytes)
    
        > 4096 ?
        kernel.shmmni:                //    maximum number of shared memory segments.
    
        <= 4096 ?
        <= kernel.shmmni
        kernel.shmseg:                //    maximum number of shared memory segments / process.
    
        kernel.shmall                //    total amount of shared memory (in pages).
        kernel.shmall = ceil(kernel.shmmax/PAGE_SIZE).
    
        kernel.shm_use_phys: 0        //
    
    
    
     
  4. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    3 456
    J'aime reçus:
    27
    Pardon

    Pour les intéressés par le concept de lock non bloquant, dernière version :

    Je ne fais plus de remove de shm, les shm restent en RAM jusqu'à ce qu'elles soient supprimées par le programme delete_shm.php lancé par crontab toutes les trente minutes.

    Le fichier $filename doit représenter la ressource faisant l'objet du lock.

    Le paramètre cache, c'est si on utilise la classe de cache html de noren ou non.

    Le LOG_FILE se remplit dès qu'il y a au moins un lock non immédiat.

    Pour l'instant, depuis ce matin, il n'y a rien dedans.

    La fonction micro_sleep($usec), attend $usec micro secondes.

    Elle utilise la fonction time_nano_sleep(), ou usleep() sinon.

    Maintenant, je vais loguer en Javascript les points de ralentissement de mon site.

    Pour l'instant, j'ai 99%, 97%, et 100% pour : Performances, Accessibilité, et le reste.

    Bien à vous.



    PHP:


    <?php
    class Semaphore_non_blocking {
        const 
    SHARED_MEMORY 100;
        const 
    LOG_FILE "/var/www/html/shm_log/cache.txt";
        private 
    $FILE_NAME            null;
        private 
    $IS_CACHE            null;
        private 
    $result_lock            null;
        private 
    $log                null;
        private 
    $fp_log                null;
        private 
    $projectId            null;
        private 
    $resourceSemaphore    null;
        private 
    $tokenSemaphore        null;
        private 
    $tokenValue            null;
        private 
    $resourceSemaphoreKey    null;
        private 
    $tokenSemaphoreKey        null;
        private 
    $tokenValueKey            null;
        public function 
    __construct($filename$is_cache false) {
            
    $this->FILE_NAME $filename;
            
    $this->IS_CACHE = ($is_cache === false) ? "FALSE" "TRUE";
            if(
    $is_cache === false) {
                
    $this->projectId    "aplusbegalix";
            } else {
                
    $this->projectId    "abraracourcix";
            }
            
    $var $filename "_" $this->projectId;
            
    $this->resourceSemaphoreKey    = (int)preg_replace("/[^0-9]/","",(preg_replace("/[^0-9]/","",md5($var))/35676248)/619876); // text to number system.
            
    $this->tokenSemaphoreKey    $this->resourceSemaphoreKey 1387655434;
            
    $this->tokenValueKey        $this->resourceSemaphoreKey 2386421167;
            if((
    $this->resourceSemaphoreKey    == -1) ||
                (
    $this->tokenSemaphoreKey == -1) ||
                (
    $this->tokenValueKey == -1)) {
                echo 
    "failed to get key of semaphore. <br />\n";
                return 
    false;
            }
            
    $this->resourceSemaphore sem_get($this->resourceSemaphoreKey10666true);
            
    $this->tokenSemaphore sem_get($this->tokenSemaphoreKey10666true);
            
    $this->tokenValue shm_attach($this->tokenValueKeyself::SHARED_MEMORY0666);
            if((
    $this->resourceSemaphore === false) ||
                (
    $this->tokenSemaphore === false) ||
                (
    $this->tokenValue === false)) {
                echo 
    "failed to get semaphore. <br />\n";
                return 
    false;
            }
            
    $this->result_lock $this->LOCK();
            return 
    $this;
        }
        public function 
    __destruct() {
            if(
    $this->result_lock) {
                
    $this->release();
            }
            
    //                @shm_remove($this->tokenValue);
            
    @shm_detach($this->tokenValue);
            @
    sem_remove($this->tokenSemaphore);
            @
    sem_remove($this->resourceSemaphore);
        }
        private function 
    myEcho($v) {
            return  
    "\t\t" $v  ' à : ' microtime(true) . "\n";
        }
        private function 
    try_lock() {
            
    //    $this->myEcho('begin try_lock()');
            //    $this->myEcho('acquire token semaphore');
            
    sem_acquire($this->tokenSemaphore);
            
    //    $this->myEcho('    token semaphore acquired');
            
    $tmp = @shm_get_var($this->tokenValue$this->tokenValueKey);
            
    //    $this->myEcho('    token value: ' . var_export($tmp, true));
            
    $exit $tmp;
            if (!
    $exit) {
                
    $tmp = @shm_put_var($this->tokenValue$this->tokenValueKeytrue);
                
    //         $tmp = @shm_get_var($this->tokenValue, $this->tokenValueKey);
                //    $this->myEcho('    token new value: ' . var_export($tmp, true));
            
    }
            
    //    $this->myEcho('release token semaphore');
            
    sem_release($this->tokenSemaphore);
            if (
    $exit) return false;
            
    //    $this->myEcho('acquire resource semaphore');
            
    sem_acquire($this->resourceSemaphore);
            
    //    $this->myEcho('    resource semaphore acquired');
            
    return true;
        }
        private function 
    release() {
            
    //    $this->myEcho('release resource semaphore');
            
    sem_release($this->resourceSemaphore);
            
    //    $this->myEcho('acquire token semaphore');
            
    sem_acquire($this->tokenSemaphore);
            
    //    $this->myEcho('    token semaphore acquired');
            //            $tmp = @shm_get_var($this->tokenValue, $this->tokenValueKey);
            // $this->myEcho('    token value: ' . var_export($tmp, true));
            
    $tmp = @shm_put_var($this->tokenValue$this->tokenValueKeyfalse);
            
    //            $tmp = @shm_get_var($this->tokenValue, $this->tokenValueKey);
            //     $this->myEcho('    token new value: ' . var_export($tmp, true));
            //    $this->myEcho('release token semaphore');
            
    sem_release($this->tokenSemaphore);
        }
        private function 
    LOCK() {
            
    $this->log "";
            for (
    $triesLeft 1000$triesLeft && !$this->try_lock(); $triesLeft--) {
                
    $this->log .= $this->myEcho('failed to acquire resource at : ' $triesLeft);
                
    $this->log .= $this->myEcho('wait for 1/1000 sec');
                
    micro_sleep(1000);
                
    $this->log .= $this->myEcho('try again');
            }
            if(
    $triesLeft <= 0) {
                
    $this->log .= $this->myEcho('hardly failed to acquire resource');
            }
            if(!empty(
    $this->log)) {
                
    $tmp "\t\tFILE = " $this->FILE_NAME "\t\tCACHE = " $this->IS_CACHE "\n";
                
    $tmp .= $this->log;
                   
                
    file_put_contents(self::LOG_FILE$tmpFILE_APPEND);
            }
            if(
    $triesLeft <= 0) {
                return 
    false;
            }
            return 
    true;
            
    //paste here your code, accessing your resource
            //                $this->release();
        
    }
    }

    ?>

     
  5. ortolojf
    ortolojf WRInaute accro
    Inscrit:
    14 Août 2002
    Messages:
    3 456
    J'aime reçus:
    27
    Bonjour

    Un programme trouvé sur www.php.net

    J'ai amélioré ma classe de verrou non bloquant.

    Les identificateurs de sémaphores et mémoire partagée sont théoriquement avec le minimum de collision.

    L'implémentation dépend du serveur ( 64 / 32 bits ), là c'est pour 64 bits.

    Pour verrouiller :

    $LOCK = new Semaphore_non_blocking($filename, $is_cache);


    Pour déverrouiller ( obligatoire ) :

    unset($LOCK);

    Voilà le code :

    PHP:

    <?php
    class Semaphore_non_blocking {

            const 
    SHARED_MEMORY 100;
            const 
    LOG_FILE "/var/www/html/shm_log/cache.txt";
            private 
    $FILE_NAME            null;
            private 
    $IS_CACHE            null;
            private 
    $result_lock            null;
            private 
    $log                null;
            private 
    $fp_log                null;
            private 
    $projectId            null;
            private 
    $resourceSemaphore    null;
            private 
    $tokenSemaphore        null;
            private 
    $tokenValue            null;
            private 
    $resourceSemaphoreKey    null;
            private 
    $tokenSemaphoreKey        null;
            private 
    $tokenValueKey            null;
            public function 
    __construct($filename$is_cache false) {
                    
    $this->FILE_NAME $filename;
                    
    $this->IS_CACHE = ($is_cache === false) ? "FALSE" "TRUE";
                    if(
    $is_cache === false) {
                            
    $this->projectId    "aplusbegalix";
                    } else {
                            
    $this->projectId    "abraracourcix";
                    }
                    
    $var $filename "_" $this->projectId;
                    
    $this->resourceSemaphoreKey    $this->tmp_ftok($var"n");
                    echo 
    "\t\t" '$this->resourceSemaphoreKey = ' $this->resourceSemaphoreKey "<br /><br />\n";
                    
    $this->tokenSemaphoreKey    $this->tmp_ftok($var"s");
                    echo 
    "\t\t" '$this->tokenSemaphoreKey = ' $this->tokenSemaphoreKey "<br /><br />\n";
                    
    $this->tokenValueKey        $this->tmp_ftok($var"u");
                    echo 
    "\t\t" '$this->tokenValueKey = ' $this->tokenValueKey "<br /><br />\n";
                    if((
    $this->resourceSemaphoreKey    === false) ||
                            (
    $this->tokenSemaphoreKey === false) ||
                            (
    $this->tokenValueKey === false)) {
                            echo 
    "failed to get key of semaphore. <br />\n";
                            return 
    false;
                    }
                    
    $this->resourceSemaphore sem_get($this->resourceSemaphoreKey10666true);
                    
    $this->tokenSemaphore sem_get($this->tokenSemaphoreKey10666true);
                    
    $this->tokenValue shm_attach($this->tokenValueKeyself::SHARED_MEMORY0666);
                    if((
    $this->resourceSemaphore === false) ||
                            (
    $this->tokenSemaphore === false) ||
                            (
    $this->tokenValue === false)) {
                            echo 
    "failed to get semaphore. <br />\n";
                            return 
    false;
                    }
                    
    $this->result_lock $this->LOCK();
                    return 
    $this;
            }
            public function 
    __destruct() {
                    if(
    $this->result_lock) {
                            
    $this->release();
                    }
                    
    //                @shm_remove($this->tokenValue);
                    
    @shm_detach($this->tokenValue);
                    @
    sem_remove($this->tokenSemaphore);
                    @
    sem_remove($this->resourceSemaphore);
            }
            private function 
    tmp_ftok($filename ""$proj "")
            {
                    if(empty(
    $filename))
                    {
                            return 
    false;
                    }
                    
    $var $filename . (string)$proj;
                    
    $nbre  = (int)floor(round(hexdec(hash('sha256'$var))) / 2147483647214748364721474836472147483647214748364721474836472147483);
                    return 
    $nbre;
            }
            private function 
    myEcho($v) {
                    return  
    "\t\t" $v  ' à : ' microtime(true) . "\n";
            }
            private function 
    try_lock() {
                    
    //    $this->myEcho('begin try_lock()');
                    //    $this->myEcho('acquire token semaphore');
                    
    sem_acquire($this->tokenSemaphore);
                    
    //    $this->myEcho('    token semaphore acquired');
                    
    $tmp = @shm_get_var($this->tokenValue$this->tokenValueKey);
                    
    //    $this->myEcho('    token value: ' . var_export($tmp, true));
                    
    $exit $tmp;
                    if (!
    $exit) {
                            
    $tmp = @shm_put_var($this->tokenValue$this->tokenValueKeytrue);
                            
    //         $tmp = @shm_get_var($this->tokenValue, $this->tokenValueKey);
                            //    $this->myEcho('    token new value: ' . var_export($tmp, true));
                    
    }
                    
    //    $this->myEcho('release token semaphore');
                    
    sem_release($this->tokenSemaphore);
                    if (
    $exit) return false;
                    
    //    $this->myEcho('acquire resource semaphore');
                    
    sem_acquire($this->resourceSemaphore);
                    
    //    $this->myEcho('    resource semaphore acquired');
                    
    return true;
            }
            private function 
    release() {
                    
    //    $this->myEcho('release resource semaphore');
                    
    sem_release($this->resourceSemaphore);
                    
    //    $this->myEcho('acquire token semaphore');
                    
    sem_acquire($this->tokenSemaphore);
                    
    //    $this->myEcho('    token semaphore acquired');
                    //            $tmp = @shm_get_var($this->tokenValue, $this->tokenValueKey);
                    // $this->myEcho('    token value: ' . var_export($tmp, true));
                    
    $tmp = @shm_put_var($this->tokenValue$this->tokenValueKeyfalse);
                    
    //            $tmp = @shm_get_var($this->tokenValue, $this->tokenValueKey);
                    //     $this->myEcho('    token new value: ' . var_export($tmp, true));
                    //    $this->myEcho('release token semaphore');
                    
    sem_release($this->tokenSemaphore);
            }
            private function 
    LOCK() {
                    
    $this->log "";
                    for (
    $triesLeft 1000$triesLeft && !$this->try_lock(); $triesLeft--) {
                            if(
    $triesLeft == 1000) {
                                    
    $this->log .= $this->myEcho('failed to acquire resource at : ' $triesLeft);
                                    
    $this->log .= $this->myEcho('wait for 1/1000 sec');
                            }
                            
    micro_sleep(1000);
                    }
                    if(
    $triesLeft 1000) {
                            
    $this->log .= $this->myEcho('try again');
                            
    $tmp "\t\tFILE = " $this->FILE_NAME "\t\tCACHE = " $this->IS_CACHE "\n";
                            
    $tmp .= $this->log;
                            
    file_put_contents(self::LOG_FILE$tmpFILE_APPEND);
                    }
                    if(
    $triesLeft <= 0) {
                            return 
    false;
                    }
                    return 
    true;
                    
    //paste here your code, accessing your resource.
            
    }
    }
    ?>

     
Chargement...
Similar Threads - Lock bloquant versus Forum Date
Du nouveau chez Adsense? Mes ads ne sont plus bloquées par les AdBlockers! AdSense 21 Août 2020
Est ce qu'on a le droit de placer des Blocks Adsense avec position:fixed ? AdSense 22 Janvier 2020
Ajouter style="display: block;" dans une div Développement d'un site Web ou d'une appli mobile 8 Janvier 2020
Comment analyser et monétiser le Trafic Adblock ! Monétisation d'un site web 9 Octobre 2019
Un même block sur desktop et mobile ou 2 blocks differents ? AdSense 20 Septembre 2019
Monétiser son audience et contrer AdBlock Monétisation d'un site web 27 Mai 2019
Proposition de solution simple, éthique et respectueuse à AdBlock Demandes d'avis et de conseils sur vos sites 7 Janvier 2016
Ad4adblock pour afficher des pubs aux utilisateurs de Adblock Demandes d'avis et de conseils sur vos sites 9 Novembre 2015
On va tous mourir ? [adblock, blocage de la pub] Monétisation d'un site web 31 Juillet 2015
Script anti-adblock Développement d'un site Web ou d'une appli mobile 31 Mars 2015