- Em um benchmark do desenvolvedor independente Theo Browne, o Cloudflare Workers apresentou desempenho até 3,5 vezes mais lento que o Node.js da Vercel
- A causa dos resultados do benchmark esteve em vários problemas de infraestrutura, configuração de bibliotecas e metodologia do benchmark
- Foram feitas diversas melhorias de plataforma e framework, como aprimoramento do algoritmo de agendamento, ajuste do coletor de lixo do V8 e otimizações no OpenNext
- Com os principais patches, agora a diferença de desempenho entre Cloudflare e Vercel diminuiu bastante na maioria dos benchmarks
- Daqui para frente, a Cloudflare pretende continuar contribuindo para melhorias abertas de infraestrutura e frameworks, além de manter otimizações contínuas e validação de benchmarks
Visão geral e controvérsia do benchmark
- Em outubro de 2023, o desenvolvedor Theo Browne publicou um benchmark comparando a velocidade de execução de JavaScript no servidor entre Cloudflare Workers e Vercel (baseada em AWS Lambda)
- O Cloudflare Workers também usa o motor JavaScript V8, assim como a Vercel, mas foi observada uma queda de desempenho de até 3,5x
- Uma diferença de desempenho injustificável surgiu por vários fatores, como microajustes de infraestrutura, diferenças entre bibliotecas JavaScript e problemas no método de teste
- No processo de corrigir esses pontos, o desempenho geral do Cloudflare Workers melhorou
- Entre as principais correções, houve inclusive melhorias como aumento da velocidade de operações trigonométricas, que podem afetar outras plataformas
Metodologia do benchmark
- O cliente de teste inicial de Theo acessava via Webpass a partir de San Francisco, e a Vercel era executada na região sfo1
- Na Cloudflare, a comunicação foi feita diretamente com a instância iad1 da Vercel dentro do datacenter AWS us-east-1, minimizando o impacto da latência de rede
- Todos os benchmarks foram realizados em ambiente de thread única (1 vCPU), o que também facilitou alinhar a comparação de preços
- Bugs encontrados durante os testes foram enviados upstream em Pull Requests e corrigidos
Melhorias de desempenho na plataforma Cloudflare
Melhorias no agendamento e no tratamento de isolamento do Workers Runtime
- Antes, era usado um algoritmo que roteava tráfego para isolamentos "quentes" (instâncias prontas para processar rapidamente) para otimizar latência e throughput de apps de grande escala, mas isso era ineficiente para cargas de trabalho intensivas em CPU
- Quando muitas requisições com alto uso de CPU se concentravam, a fila aumentava e a latência crescia, algo que apareceu no benchmark
- Como o critério de cobrança do Cloudflare Workers é o tempo de uso de CPU, o tempo de espera (aguardando preparação do isolamento) não é cobrado
- Com a reformulação do algoritmo, o sistema passou a detectar mais rapidamente workloads com alto consumo de CPU e a criar novos isolamentos com mais agilidade
- Isso melhorou a resposta tanto para workloads limitadas por I/O quanto por CPU, e a mudança foi distribuída globalmente com efeito imediato
Melhorias na configuração do coletor de lixo do V8
- Durante os testes, foi confirmado que problemas de coleta de lixo do JavaScript e gerenciamento de memória tinham grande impacto na queda de desempenho
- A configuração do tamanho da área de memória "young generation" do motor V8 estava rigidamente limitada demais (ajustada ao antigo valor recomendado de 128MB)
- Nas versões mais recentes do V8, essa forma de configuração passou a provocar GCs frequentes desnecessários
- O ajuste manual foi removido, permitindo a alocação dinâmica de memória com base nas heurísticas do próprio V8
- Foi observada uma melhoria de cerca de 25% no benchmark, aplicada a todos os Workers
Otimização de desempenho do Next.js com base no OpenNext
Remoção de alocação e cópia desnecessárias de memória
- A análise mostrou que 10–25% do tempo de processamento de requisições era gasto com liberação de memória (GC)
- OpenNext, Next.js e React tinham vários padrões de código que copiavam buffers de dados internos em excesso
- Havia cópia desnecessária de toda a saída de dados de stream, e grandes volumes de dados eram copiados com
Buffer.concat apenas para medir tamanho
- Esses problemas estão sendo melhorados por meio de Pull Requests no repositório do OpenNext
- O plano é continuar evoluindo isso para que a melhoria de desempenho beneficie de forma ampla toda a plataforma
Otimização de adaptadores de stream ineficientes
- O Workers usa a Web Streams API, enquanto o Next.js é projetado principalmente em torno da API de streams do Node.js, exigindo adaptadores de conversão
- O uso de adaptadores aninhados desnecessários gerava bastante overhead de cópia de memória e buffering
- O código foi simplificado para
ReadableStream.from(chunks), removendo cópias intermediárias
- A estrutura padrão de stream de valor único (
highWaterMark=1) foi melhorada para stream de bytes (highWaterMark=4096 etc.), otimizando o processamento de grandes volumes de dados
- Futuramente, patches para melhorar o processamento de streams no Next.js e no React também devem ser enviados upstream
Problema de desempenho de JSON.parse() e patch no V8
- Em Next.js e React de forma geral, o uso de
JSON.parse() com a opção reviver gerava chamadas excessivas (mais de 100.000 vezes)
- O padrão ECMAScript mais recente permite receber um terceiro argumento (contexto da origem) no reviver, o que agravou ainda mais o desempenho (em Firefox, Chrome etc.)
- A equipe do Cloudflare Workers forneceu um patch para o motor V8 (melhoria de 33% no desempenho), que deve beneficiar todo o ecossistema, incluindo Node.js, navegador Chrome e Deno
Problema de desempenho de funções trigonométricas no Node.js
- Separadamente do benchmark de Theo, foi relatado que, em um benchmark de chamadas repetidas de funções trigonométricas matemáticas (
sin, cos etc.), o Cloudflare Workers foi 3x mais rápido
- A causa foi que o Node.js ainda não havia acompanhado o caminho mais novo/rápido de funções trigonométricas oferecido pelo V8 (flag de compilação)
- O Cloudflare Workers tinha essa flag ativada por padrão por acaso, e um patch foi enviado em Pull Request para o Node.js
- Como esse problema também é comum ao ecossistema open source, espera-se maior estabilidade geral de velocidade quando isso for refletido também em AWS Lambda e Vercel
Limitações e lições de projeto/medição do benchmark
- A maior parte dos benchmarks mediu tempo de requisição (latência) do lado do cliente, sem medir diretamente o tempo real de uso de CPU no servidor
- Vários fatores não comparáveis podem afetar o resultado, como rota de rede, localização do datacenter, geração do hardware e multitenancy
- Quando se mede apenas o tempo até o primeiro byte da resposta (TTFB), é difícil refletir todo o tempo de renderização/transmissão. Ao mudar para TTFL, a medição pode ficar ainda mais sensível às diferenças de velocidade de rede
- Dependendo da diversidade de hardware/software do servidor e da sorte no provisionamento de instâncias, também existe ruído temporário ou correlacionado
- Ao definir com mais precisão o ambiente e o fluxo de trabalho para benchmark e alinhar as variáveis, foi possível extrair melhorias práticas úteis tanto para a própria plataforma quanto para plataformas de terceiros
Problemas descobertos durante o experimento em benchmark e configuração de ambiente
- Havia risco de interpretação errada dos resultados devido a fatores como ausência de aplicação da configuração force-dynamic do Next.js, lógica de cache e diferenças no método de streaming de resposta
- No benchmark de React SSR, a variável de ambiente
NODE_ENV não estava definida, fazendo o sistema rodar em modo de desenvolvimento e retornar resultados mais lentos do que o real
- Esses erros foram corrigidos definindo explicitamente as variáveis de ambiente
Planos futuros e conclusão
- Várias melhorias de desempenho no Cloudflare Workers Runtime já foram aplicadas amplamente, e os usuários se beneficiam delas sem precisar fazer nada
- Foram fornecidos ao Theo Pull Requests com código de teste e otimizações do OpenNext refletidas
- Estão previstas melhorias adicionais para reduzir a diferença entre OpenNext e o Next.js baseado na Vercel
- A diretriz é continuar atualizando o algoritmo de agendamento e os motores open source (V8, Node.js), além de contribuir com a comunidade
- Com benchmarks e profiling melhores, a ideia é detectar mais cedo problemas potenciais e manter a cultura de otimização e compartilhamento
Materiais de referência e links adicionais
1 comentários
Comentários do Hacker News
É bom ver a CF realmente tentando melhorar o produto. Mas as mudanças acontecem rápido demais e é difícil acompanhar, e muitas vezes os lançamentos vêm antes da maturidade. Por exemplo, o R2 Data Catalog ainda carece de suporte ao Iceberg v3, o Wrangler mudou bastante em apenas alguns meses, e parece que o Pages vai desaparecer em breve, então a migração para o Workers Assets é bem incômoda. Configurações que funcionavam bem no Wrangler 3 não foram aplicadas corretamente no Wrangler 4, e dá a sensação de que no Wrangler 5 virá mais um novo modelo de interação
Sobre a frase “parece que o Pages vai desaparecer”, a própria CF mencionou em um post da comunidade que não vai encerrar o Pages até que o Workers esteja no mesmo nível do Pages Post relacionado É difícil encontrar qualquer anúncio oficial de descontinuação do Pages, e tanto pages.cloudflare.com quanto developer.cloudflare.com/pages seguem ativos. Um post no Reddit sugere a migração do Pages, mas mesmo naquele link não há qualquer menção oficial de encerramento Concordo com o restante da opinião, mas essa parte especificamente me surpreendeu Link de referência no Reddit
Não concordo com a afirmação de que as configurações do Wrangler 3 não funcionam igual no Wrangler 4. No Wrangler 4 não houve nenhuma mudança no formato de configuração, e o aumento de versão major não afetou 99,99% dos usuários. As mudanças correspondentes podem ser vistas aqui. O simples aumento de major version já causa bastante incômodo, então eu mesmo manifestei oposição internamente, mas a equipe foi cautelosa por causa de casos raríssimos de exceção. No futuro, vamos desenvolver formas de lidar com esse tipo de questão sem precisar de um aumento de versão major, como suporte paralelo a versões do esbuild. Do lado do runtime, temos um cuidado enorme especialmente com retrocompatibilidade Blog sobre retrocompatibilidade O Pages não vai desaparecer, e o Workers Assets é uma versão mais flexível da implementação do Pages. Se você não precisa de funcionalidades extras, não há necessidade de migrar agora, e mais adiante também haverá migração automática
Isso só reforça que, ao criar projetos importantes ou sistemas que serão mantidos por anos, vale usar “boring tech”
Fiquei curioso para saber de onde veio a ideia de que “parece que o Pages vai desaparecer”. Eu uso o Pages tranquilamente em vários projetos
O curioso é que toda essa discussão começou com a alegação de que a Cloudflare era mais rápida que a Vercel. Depois, alguém que realmente entendia do assunto fez os benchmarks e descobriu que o resultado real era o oposto. No fim, a Cloudflare passou a fazer melhorias concretas para elevar o desempenho
Gostei muito da postura do artigo: em vez de atacar a concorrência, ele identifica e destaca pontos de melhoria. Também achei impressionante ver avanços na implementação do OpenNext que podem ser reaproveitados por outros fornecedores
Estou migrando um app NextJS hospedado na Vercel para Astro/React na Cloudflare. O impressionante é que, mesmo renderizando o webapp no “edge” a cada requisição, o tempo de resposta fica na faixa de 100–200 ms, praticamente comparável a páginas estáticas. Também senti claramente as melhorias recentes do Cloudflare Worker nas últimas semanas: cold starts quase sumiram e a velocidade de resposta ficou muito mais estável Link do webapp em migração
Acho curioso como um vídeo publicado por um youtuber não tão grande conseguiu se espalhar de forma tão eficaz e levar a Cloudflare a fazer melhorias realmente significativas e resolver problemas da plataforma
PR bem executado demais. Parabéns a quem preparou este post
Falando como cliente antigo da cf: a cf manda muito bem em posts de blog e textos de open source, mas entre empresas de infraestrutura também é a melhor em suporte de serviço. Membros da equipe, incluindo o kenton, frequentemente ajudam usuários diretamente no Discord ou acolhem feedback, e em bugs ou problemas muitas vezes dá para falar direto com o engenheiro responsável. Já tive PRs e feature requests meus incorporados rapidamente sem grande burocracia. Mesmo pagando muito menos do que em outras big techs, recebo um suporte muito melhor
Obrigado! Este PR e este post foram 100% idealizados e produzidos de forma autônoma pelos engenheiros da equipe de Workers (eu também participei)
Gosto muito da forma como este post foi escrito, da decomposição das informações e da discussão aberta. Isso aumentou minha confiança na equipe de Cloudflare Workers
Na minha opinião, o SvelteKit é extremamente rápido, e o Next.js é relativamente muito lento
Parece uma conclusão plausível
Tomara que frameworks mais pragmáticos, como SvelteKit, Astro e TanStack, logo substituam a complexidade do NextJS
Casos assim mostram por que concorrência e benchmarks independentes são necessários. Até serviços com desempenho ruim acabam sendo incentivados a melhorar
Mas esse esforço só funciona quando a empresa realmente se importa com o produto
Benchmarks independentes já existem
Foi impressionante ver a Cloudflare aceitar o resultado com humildade e melhorar de forma construtiva
É um ótimo texto, focado no conteúdo e sem ataques. Mas me surpreendeu que a Cloudflare aparentemente não estivesse monitorando e ajustando melhor antecipadamente coisas como o tamanho das generations. Na minha experiência com tuning de desempenho de JVM, configurar generation size era algo básico