Adotamos um projeto da web python órfão esta semana, que foi mantido por vários desenvolvedores uma vez. Os antigos mantenedores não pararam com o mau cheiro do projeto. ~ 5s, que terrível), os usuários reclamam, temos que enfrentar o problema e resolvê-lo.
Meu mentor percebeu que havia vários SELECT COUNT
s na página do painel. Não fazia sentido torná-lo tão em tempo real:
class Car(model):
@classmethod
def count(cls, category):
# select count from db
A otimização estava apenas armazenando em cache o resultado da contagem :
class Car(model):
@classmethod
@cache('car:{category}:count', expire=30)
def count(cls, category):
# select count from db
Usei essa forma rápida e não suja. Então os usuários sentiram a melhora na velocidade na página do painel.
Mas você entrou em todas as páginas da lista de categorias, ainda lento. Myql explain mostrou que o tipo de consulta de categoria é all
, o pior tipo possível. A consulta contém duas condições where e um pedido. Tentei adicionar índice a um de onde condição, tipo se tornou. range
Depois de adicionar índices a outros campos, tornou-se ref
, o que pode ser aceito.
Naquela época, o custo médio da solicitação era de 1.000 ms.
Graças à equipe do app engine, adicionando app_engine_profile=true
a cada URL, podemos facilmente obter os detalhes para criação de perfil. Eu tentei, gzip
foram chamados 60.000 vezes e custaram 400 ms no ambiente de produção, mas outros projetos não mostraram essas chamadas gzip anormais. Com a dica de meu mentor, examinei o ponto de entrada do aplicativo.
Quando comentei totalmente o middleware gzip, o tempo de solicitação diminuiu de 120ms para 20ms no ambiente de desenvolvimento. Estava convencido de que havia alguns pontos de acesso relacionados ao gzip, então percebi o valor de retorno do aplicativo:
class Publisher(object):
def __call__(self, env, start_response):
body = 'string'
return body # Iterable object.
Uau, todo mundo sabe que é um objeto iterável e cada artigo sobre WSGI dirá a você não enviar a saída um byte por um byte , mas os desenvolvedores ainda fizeram isso . Isso fez com que o gzip fosse aplicado a cada byte. Alterando ou resolvendo este problema.return [body]
yield body
Esta tarde, quando implantei o código modificado para o teste, o ambiente de produção gerou muitas exceções causadas pelo cache do mako. Verifiquei, o projeto salvou o cache do mako no mfs e os dois ambientes usaram o mesmo cache do mako. Depois de resolver esse bug, a velocidade pode ser um pouco melhor, porque mfs é um sistema de arquivos de rede distribuído.
No final, o desempenho do projeto teve uma melhora considerável, mas ainda havia muito trabalho a ser feito.