Re: [Python] threading, local() and uwsgi: how protected is local()? - RITENTO

2017-12-13 Per discussione Marco Giusti
On 13/12/17 09:12, Alessandro Dentella wrote:
...
> Avendo sollecitato Roberto De Ioris anche in privato, mi ha in effetti
> risposto:
> 
> Ciao, di solito si usano i thread local per avere dati
> NON-condivisi tra i thread. Se e' il tuo caso, allora puoi usarli
> senza problemi a patto che abiliti il GIL in uWSGI con
> --enable-threads.
> 
> Va da sè che se non abilito --enable-threads, problema non ne ho,
> visto che non uso threads... e --threads imploca --enable-threads.

Esatto. Questa era anche la mia sensazione.

>> In realta' e' l'altro risultato che mi lascia dei dubbi, quando
>> threading.local non e' usato.
> 
> Qui ti ho perso... quale sarebbe "l'altro risultato"?

Lancia i test che ho mandato, una volta con la variabile d'ambiente
thread_safe=1 e la seconda senza. Quando il test non usa
threading.local, il risultato mi lascia perplesso. Il test lancia 400
richieste, mi aspetto che il totale sia x <= 400 e invece e'
costantemente > 400.
___
Python mailing list
Python@lists.python.it
https://lists.python.it/mailman/listinfo/python


Re: [Python] threading, local() and uwsgi: how protected is local()? - RITENTO

2017-12-13 Per discussione Alessandro Dentella
Ciao Marco,


grazie per la risposta e l'attenzione.

> > al lavoro abbiamo avuto una interessante discussione su un modo di
> > tenere in Django una informazione sempre disponibile (request / user e
> > recentemente un 'dominio').
> >
> > Una soluzione a volte considerata "da evitare" ma che ci è sempre
> > andata bene è stata fatta seguendo un vecchio snippet di Django [2 -
> inizio]
> > che immagazzina i dati in threading local().
> >
> > Quello che mi ha fatto balzare sulla sedia ieri è che un collega mi ha
> > mostrato un post [1] su StackOverflow dove si dice che uwsgi non
> > garantisce che quello che si mette in local() non sia condiviso fra
> > thread differenti... nonostante la documentazione Python dica:
> >
> >Thread-local data are data whose values are thread specific
> >
> >
> > In una pagina citata in questo post [2] si espone una situazione molto
> > simile alla mia, ma non vedo una risposta soddisfacente sul fatto che
> > sia in effetti vero
> >
> >   * che uwsgi forza un uso condiviso della ram fra thread differenti e
> >   * se esiste un modo per bypassarlo
> >
> > io ho spesso in uwsgi.ini (ma ho anche occasionalmente di più):
> >
> >   threads: 1
> >   processors: 2
> >
> > È questo che mi ha salvato fino ad oggi?
> >
> >
> > sandro
> > *:-)
> >
> >
> > PS: tecnicamente io scrivo nel _thread_local tramite middleware ad
> > ogni request, non esiste possibilità che resti il vecchio nella
> > nuova request
>
>
> Ciao Alessandro,
>
> incuriosito dalla tua domanda e partaggiando il tuo stesso stupore ho
> fatto qualche ricerca.
>
> Prima di tutto vorrei iniziare dicendo che faccio piu' confidenza al
> gruppo di unbit piuttosto che al commento di qualcuno in un sito. Mi
> sembrava di aver letto nella documentazione di uWSGI che l'obiettivo
> principale di uWSGI sia la correttezza, le performance vengono dopo.
> Ovviamente non ritrovo la frase in questione ma che cambino la semantica
> di threading.local per ragioni di performance mi sembra un suicidio. Se
> fai un veloce grep nel codice di Django ti accorgerai che Django stesso
> usa local() internamente.
>
> Per scrupolo ho fatto una piccola ricerca nei sorgenti di uWSGI e non
> trovo conferma di una simile castroneria.
>
> Sono gia' bloccato, non so' piu' come continuare. Sono stati portati
> esempi concreti a supporto della tesi? No.
>
> Allego due file di test e come puoi verificare e threading.local
> funziona esattamente come ci si aspetterebbe.


Avendo sollecitato Roberto De Ioris anche in privato, mi ha in effetti
risposto:

Ciao, di solito si usano i thread local per avere dati
NON-condivisi tra i thread. Se e' il tuo caso, allora puoi usarli
senza problemi a patto che abiliti il GIL in uWSGI con
--enable-threads.

Va da sè che se non abilito --enable-threads, problema non ne ho,
visto che non uso threads... e --threads imploca --enable-threads.



> In realta' e' l'altro risultato che mi lascia dei dubbi, quando
> threading.local non e' usato.

Qui ti ho perso... quale sarebbe "l'altro risultato"?



sandro
*:-)
___
Python mailing list
Python@lists.python.it
https://lists.python.it/mailman/listinfo/python


Re: [Python] threading, local() and uwsgi: how protected is local()? - RITENTO

2017-12-13 Per discussione Marco Giusti
On 07/12/17 18:39, Alessandro Dentella wrote:
> ***
> Rimando nella speranza che qualcuno legga e desideri e magari stia
> cercando di combattere la noia...
> ***
>
> Ciao,
>
> [disclaimer: si parla di Django ma il tema mi pare più generale poi si
> parla di uwsgi e mi pare che Roberto qui legga...]
>
> al lavoro abbiamo avuto una interessante discussione su un modo di
> tenere in Django una informazione sempre disponibile (request / user e
> recentemente un 'dominio').
>
> Una soluzione a volte considerata "da evitare" ma che ci è sempre
> andata bene è stata fatta seguendo un vecchio snippet di Django [2 -
inizio]
> che immagazzina i dati in threading local().
>
> Quello che mi ha fatto balzare sulla sedia ieri è che un collega mi ha
> mostrato un post [1] su StackOverflow dove si dice che uwsgi non
> garantisce che quello che si mette in local() non sia condiviso fra
> thread differenti... nonostante la documentazione Python dica:
>
>Thread-local data are data whose values are thread specific
>
>
> In una pagina citata in questo post [2] si espone una situazione molto
> simile alla mia, ma non vedo una risposta soddisfacente sul fatto che
> sia in effetti vero
>
>   * che uwsgi forza un uso condiviso della ram fra thread differenti e
>   * se esiste un modo per bypassarlo
>
> io ho spesso in uwsgi.ini (ma ho anche occasionalmente di più):
>
>   threads: 1
>   processors: 2
>
> È questo che mi ha salvato fino ad oggi?
>
>
> sandro
> *:-)
>
>
> PS: tecnicamente io scrivo nel _thread_local tramite middleware ad
> ogni request, non esiste possibilità che resti il vecchio nella
> nuova request


Ciao Alessandro,

incuriosito dalla tua domanda e partaggiando il tuo stesso stupore ho
fatto qualche ricerca.

Prima di tutto vorrei iniziare dicendo che faccio piu' confidenza al
gruppo di unbit piuttosto che al commento di qualcuno in un sito. Mi
sembrava di aver letto nella documentazione di uWSGI che l'obiettivo
principale di uWSGI sia la correttezza, le performance vengono dopo.
Ovviamente non ritrovo la frase in questione ma che cambino la semantica
di threading.local per ragioni di performance mi sembra un suicidio. Se
fai un veloce grep nel codice di Django ti accorgerai che Django stesso
usa local() internamente.

Per scrupolo ho fatto una piccola ricerca nei sorgenti di uWSGI e non
trovo conferma di una simile castroneria.

Sono gia' bloccato, non so' piu' come continuare. Sono stati portati
esempi concreti a supporto della tesi? No.

Allego due file di test e come puoi verificare e threading.local
funziona esattamente come ci si aspetterebbe. In realta' e' l'altro
risultato che mi lascia dei dubbi, quando threading.local non e' usato.


Marco
from itertools import groupby
from operator import itemgetter
import threading
import urllib.request


lock = threading.Lock()
results = []


def get(url):
for i in range(200):
with urllib.request.urlopen(url) as response:
content = response.read(300).decode('ascii')
tid, c = map(int, content.split())
with lock:
results.append((tid, c))


if __name__ == '__main__':
t1 = threading.Thread(target=get, args=('http://localhost:9000', ))
t2 = threading.Thread(target=get, args=('http://localhost:9000', ))
t1.start()
t2.start()
t1.join()
t2.join()
results = sorted(results, reverse=True)
tot = 0
for group, iterable in groupby(results, itemgetter(0)):
last = next(iterable)
tot += last[1]
print('Thread: {0}, c: {1}'.format(*last))
print('Total:', tot)
# thread_safe=1 uwsgi_python3 --http-socket :9000 --module test_local --threads 3

import os
import random
from threading import local, get_ident
import time


if not os.environ.get('thread_safe', False):
class local:
pass
l = local()


def application(env, start_response):
l.__dict__.setdefault('c', 0)
c = l.c
time.sleep(0.01 + (random.random() / 50 - 0.01))
c += 1
l.c = c
response = b'%d %d' % (get_ident(), c)
headers = [
('Content-Type', 'text/plain'),
('Content-Length', str(len(response))),
]
start_response('200 Ok', headers)
return [response]
___
Python mailing list
Python@lists.python.it
https://lists.python.it/mailman/listinfo/python


[Python] threading, local() and uwsgi: how protected is local()? - RITENTO

2017-12-07 Per discussione Alessandro Dentella
***
Rimando nella speranza che qualcuno legga e desideri e magari stia
cercando di combattere la noia...
***

Ciao,

[disclaimer: si parla di Django ma il tema mi pare più generale poi si
parla di uwsgi e mi pare che Roberto qui legga...]

al lavoro abbiamo avuto una interessante discussione su un modo di
tenere in Django una informazione sempre disponibile (request / user e
recentemente un 'dominio').

Una soluzione a volte considerata "da evitare" ma che ci è sempre
andata bene è stata fatta seguendo un vecchio snippet di Django [2 - inizio]
che immagazzina i dati in threading local().

Quello che mi ha fatto balzare sulla sedia ieri è che un collega mi ha
mostrato un post [1] su StackOverflow dove si dice che uwsgi non
garantisce che quello che si mette in local() non sia condiviso fra
thread differenti... nonostante la documentazione Python dica:

   Thread-local data are data whose values are thread specific


In una pagina citata in questo post [2] si espone una situazione molto
simile alla mia, ma non vedo una risposta soddisfacente sul fatto che
sia in effetti vero

  * che uwsgi forza un uso condiviso della ram fra thread differenti e
  * se esiste un modo per bypassarlo

io ho spesso in uwsgi.ini (ma ho anche occasionalmente di più):

  threads: 1
  processors: 2

È questo che mi ha salvato fino ad oggi?


sandro
*:-)


PS: tecnicamente io scrivo nel _thread_local tramite middleware ad
ogni request, non esiste possibilità che resti il vecchio nella
nuova request

[1] 
https://stackoverflow.com/questions/3227180/why-is-using-thread-locals-in-django-bad
[2] https://www.pythonanywhere.com/forums/topic/710/
___
Python mailing list
Python@lists.python.it
https://lists.python.it/mailman/listinfo/python


[Python] threading, local() and uwsgi: how protected is local()?

2017-12-05 Per discussione Alessandro Dentella


Ciao,

[disclaimer: si parla di Django ma il tema mi pare più generale poi si
parla di uwsgi e mi pare che Roberto qui legga...]

al lavoro abbiamo avuto una interessante discussione su un modo di
tenere in Django una informazione sempre disponibile (request / user e
recentemente un 'dominio').

Una soluzione a volte considerata "da evitare" ma che ci è sempre
andata bene è stata fatta seguendo un vecchio snippet di Django [2 - inizio]
che immagazzina i dati in threading local().

Quello che mi ha fatto balzare sulla sedia ieri è che un collega mi ha
mostrato un post [1] su StackOverflow dove si dice che uwsgi non
garantisce che quello che si mette in local() non sia condiviso fra
thread differenti... nonostante la documentazione Python dica:

   Thread-local data are data whose values are thread specific


In una pagina citata in questo post [2] si espone una situazione molto
simile alla mia, ma non vedo una risposta soddisfacente sul fatto che
sia in effetti vero

  * che uwsgi forza un uso condiviso della ram fra thread differenti e
  * se esiste un modo per bypassarlo

io ho spesso in uwsgi.ini (ma ho anche occasionalmente di più):

  threads: 1
  processors: 2

È questo che mi ha salvato fino ad oggi?


sandro
*:-)


PS: tecnicamente io scrivo nel _thread_local tramite middleware ad
ogni request, non esiste possibilità che resti il vecchio nella
nuova request

[1] 
https://stackoverflow.com/questions/3227180/why-is-using-thread-locals-in-django-bad
[2] https://www.pythonanywhere.com/forums/topic/710/
___
Python mailing list
Python@lists.python.it
https://lists.python.it/mailman/listinfo/python