Pular para o conteúdo
Development

Consertando o load path da History, e me pegando comentando demais o ajuste

Por Victor Da Luz
iosswiftperformancedev-logdeep-cut-atlas

Este app foi renomeado depois para Deep Cut Atlas. Ele é chamado de “Discoverer” ao longo do texto abaixo, porque era assim que se chamava no dia em que isso aconteceu.

Terceira passada de performance da semana no Discoverer, desta vez na aba History. A mesma revisão que pegou os problemas da aba Discover sinalizou três problemas aqui também, todos no código que carrega e pagina suas faixas tocadas recentemente.

O primeiro já era familiar a essa altura: três fetches que deveriam ser independentes estavam rodando um atrás do outro. Conteúdo da playlist, depois uma varredura completa das chaves de álbum da biblioteca, depois a primeira página de faixas tocadas recentemente. Tudo sequencial, tudo bloqueando a tela de mostrar qualquer coisa. A pegadinha desta vez foi que um desses três fetches, a varredura das chaves da biblioteca, nem era necessário para renderizar a lista. Ele só importava depois, para controlar um botão numa detail sheet que abre quando você toca numa linha. Estava carregando de cara puramente por hábito, não porque a tela precisava disso.

O ajuste teve duas partes. Primeiro, disparar o fetch da playlist e o fetch da primeira página ao mesmo tempo usando uma Task simples e não estruturada, a mesma solução alternativa de alguns dias atrás, já que a sintaxe mais limpa async let do Swift não funciona contra esse tipo de serviço main-actor. Segundo, fazer a varredura das chaves da biblioteca rodar de forma preguiçosa, uma vez por sessão, depois que a tela já está mostrando alguma coisa. Já existia um exemplo funcionando desse mesmo padrão em outro lugar do app, na aba Playlist, então copiei a forma dele em vez de inventar uma nova.

Os outros dois problemas eram menores, mas mostravam o mesmo formato de erro: fazer repetidamente um trabalho que podia ter sido feito uma vez só. Um ponto recalculava uma lista filtrada toda vez que uma linha entrava na tela, em vez de uma vez por desenho de tela. Outro recalculava uma contagem corrente do zero a cada página de resultados, em vez de simplesmente manter um total corrente. Nenhum dos dois é dramático numa lista pequena. Os dois viram um atraso real e perceptível conforme a lista cresce, porque o custo escala com o quadrado do tamanho da lista em vez de linearmente.

A parte que eu não esperava estar escrevendo

No meio do caminho, meus ajustes de uma linha tinham crescido para um pequeno ensaio de comentários de “por quê” grudado em cada um, explicando o raciocínio por trás de cada mudança. Na hora, parecia responsável. Aí o arquivo estourou uma regra de linter de contagem de linhas, e tive que voltar e cortar quase tudo que tinha acabado de escrever, função por função, só para trazer o arquivo de volta para dentro do limite. Foi aí que caiu a ficha: eu não estava escrevendo comentários porque o código precisava deles. Estava escrevendo porque tinha acabado de raciocinar sobre algo complicado, e digitar aquilo parecia uma prova do trabalho feito. O código não ficou mais difícil de ler sem eles. Pelo contrário, algumas das versões cortadas ficaram mais limpas de ler, porque um comentário que só repete “fazemos X porque Y” muitas vezes significa que X e Y deveriam ter tido um nome melhor desde o início.

Acabei escrevendo para mim mesmo uma regra mais rígida sobre isso antes de seguir em frente: antes de adicionar qualquer comentário, checar se removê-lo realmente perde informação que o leitor não consegue obter de outra forma, se ele cobre uma exceção genuína em vez de lógica de rotina, e se um nome melhor teria tornado ele desnecessário. Se não passar nos três, não escrever. Coisa pequena, mas já está mudando a cara do próximo diff.

Leitura relacionada

Development

O scan de 8 segundos escondido em cada refresh

Medir no dispositivo encontrou um scan da biblioteca inteira rodando em cada lote do Discover - e uma armadilha de medição de 16x onde o cache HTTP favoreceu o caminho errado.

Ler

Você também pode achar útil

Proton

Proton Drive

Armazenamento em nuvem criptografado, da equipe por trás do Proton Mail.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
Proton

Proton Pass

Gerenciador de senhas focado em privacidade, da equipe por trás do Proton Mail.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
RackNerd

RackNerd VPS

Hospedagem VPS econômica para serviços leves que funcionam continuamente.

Como afiliado da RackNerd, ganho com compras qualificadas.

Saiba mais