View in English

  • Apple Developer
    • Get Started

    Explore Get Started

    • Overview
    • Learn
    • Apple Developer Program

    Stay Updated

    • Latest News
    • Hello Developer
    • Platforms

    Explore Platforms

    • Apple Platforms
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store

    Featured

    • Design
    • Distribution
    • Games
    • Accessories
    • Web
    • Home
    • CarPlay
    • Technologies

    Explore Technologies

    • Overview
    • Xcode
    • Swift
    • SwiftUI

    Featured

    • Accessibility
    • App Intents
    • Apple Intelligence
    • Games
    • Machine Learning & AI
    • Security
    • Xcode Cloud
    • Community

    Explore Community

    • Overview
    • Meet with Apple events
    • Community-driven events
    • Developer Forums
    • Open Source

    Featured

    • WWDC
    • Swift Student Challenge
    • Developer Stories
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Centers
    • Documentation

    Explore Documentation

    • Documentation Library
    • Technology Overviews
    • Sample Code
    • Human Interface Guidelines
    • Videos

    Release Notes

    • Featured Updates
    • iOS
    • iPadOS
    • macOS
    • watchOS
    • visionOS
    • tvOS
    • Xcode
    • Downloads

    Explore Downloads

    • All Downloads
    • Operating Systems
    • Applications
    • Design Resources

    Featured

    • Xcode
    • TestFlight
    • Fonts
    • SF Symbols
    • Icon Composer
    • Support

    Explore Support

    • Overview
    • Help Guides
    • Developer Forums
    • Feedback Assistant
    • Contact Us

    Featured

    • Account Help
    • App Review Guidelines
    • App Store Connect Help
    • Upcoming Requirements
    • Agreements and Guidelines
    • System Status
  • Quick Links

    • Events
    • News
    • Forums
    • Sample Code
    • Videos
 

Vídeos

Abrir menu Fechar menu
  • Coleções
  • Todos os vídeos
  • Sobre

Mais vídeos

  • Sobre
  • Resumo
  • Código
  • Otimize o desempenho da CPU com o Instruments

    Saiba como otimizar seu app para Apple Silicon com duas novas ferramentas assistidas por hardware no Instruments. Primeiro, vamos abordar como analisar o desempenho do seu app e, em seguida, vamos mostrar em detalhes cada função chamada com o instrumento Processor Trace. Também abordaremos como usar o instrumento CPU Counters para analisar seu código em busca de gargalos da CPU.

    Capítulos

    • 0:00 - Introdução
    • 2:28 - Mentalidade de desempenho
    • 8:50 - Ferramentas de análise de desempenho
    • 13:20 - Span
    • 14:05 - Processor Trace
    • 19:51 - Análise de gargalos
    • 31:33 - Resumo
    • 32:13 - Próximas etapas

    Recursos

    • Performance and metrics
    • Analyzing CPU usage with the Processor Trace instrument
    • Apple Silicon CPU Optimization Guide Version 4
    • Tuning your code’s performance for Apple silicon
      • Vídeo HD
      • Vídeo SD

    Vídeos relacionados

    WWDC25

    • Melhore o uso da memória e o desempenho com o Swift
    • Monitore e otimize o consumo de energia do seu app
    • Otimize o desempenho do SwiftUI com o Instruments

    WWDC24

    • Explore Swift performance

    WWDC23

    • Analyze hangs with Instruments

    WWDC22

    • Visualize and optimize Swift concurrency
  • Buscar neste vídeo...
    • 6:37 - Binary search in Collection

      public func binarySearch<E, C>(
          needle: E,
          haystack: C
      ) -> C.Index where E: Comparable, C: Collection<E> {
          var start = haystack.startIndex
          var length = haystack.count
      
          while length > 0 {
              let half = length / 2
              let middle = haystack.index(start, offsetBy: half)
              let middleValue = haystack[middle]
              if needle < middleValue {
                  length = half
              } else if needle == middleValue {
                  return middle
              } else {
                  start = haystack.index(after: middle)
                  length -= half + 1
              }
          }
      
          return start
      }
    • 7:49 - Throughput benchmark

      import Testing
      import OSLog
      
      let signposter = OSSignposter(
          subsystem: "com.example.apple-samplecode.MyBinarySearch",
          category: .pointsOfInterest
      )
      
      func search(
          name: StaticString,
          duration: Duration,
          _ search: () -> Void
      ) {
          var now = ContinuousClock.now
          var outerIterations = 0
          
          let interval = signposter.beginInterval(name)
          let start = ContinuousClock.now
          repeat {
              search()
              outerIterations += 1
              now = .now
          } while (start.duration(to: now) < duration)
          let elapsed = start.duration(to: now)
          let seconds = Double(elapsed.components.seconds) +
                  Double(elapsed.components.attoseconds) / 1e18
          let throughput = Double(outerIterations) / seconds
          signposter.endInterval(name, interval, "\(throughput) ops/s")
          print("\(name): \(throughput) ops/s")
      }
      
      let arraySize = 8 << 20
      let arrayCount = arraySize / MemoryLayout<Int>.size
      let searchCount = 10_000
      
      struct MyBinarySearchTests {
          let sortedArray: [Int]
          let randomElements: [Int]
          
          init() {
              let sortedArray: [Int] = (0..<arrayCount).map { _ in
                      .random(in: 0..<arrayCount)
              }.sorted()
              self.randomElements = (0..<searchCount).map { _ in
                  sortedArray.randomElement()!
              }
              self.sortedArray = sortedArray
          }
      
          @Test func searchCollection() throws {
              search(name: "Collection", duration: .seconds(1)) {
                  for element in randomElements {
                      _ = binarySearch(needle: element, haystack: sortedArray)
                  }
              }
          }
      }
    • 13:46 - Binary search in Span

      public func binarySearch<E: Comparable>(
          needle: E,
          haystack: Span<E>
      ) -> Span<E>.Index {
          var start = haystack.indices.startIndex
          var length = haystack.count
      
          while length > 0 {
              let half = length / 2
              let middle = haystack.indices.index(start, offsetBy: half)
              let middleValue = haystack[middle]
              if needle < middleValue {
                  length = half
              } else if needle == middleValue {
                  return middle
              } else {
                  start = haystack.indices.index(after: middle)
                  length -= half + 1
              }
          }
      
          return start
      }
    • 15:09 - Throughput benchmark for binary search in Span

      extension MyBinarySearchTests {
          @Test func searchSpan() throws {
              let span = sortedArray.span
              search(name: "Span", duration: .seconds(1)) {
                  for element in randomElements {
                      _ = binarySearch(needle: element, haystack: span)
                  }
              }
          }
      
          @Test func searchSpanForProcessorTrace() throws {
              let span = sortedArray.span
              signposter.withIntervalSignpost("Span") {
                  for element in randomElements[0..<10] {
                      _ = binarySearch(needle: element, haystack: span)
                  }
              }
          }
      }
    • 19:17 - Binary search in Span

      public func binarySearchInt(
          needle: Int,
          haystack: Span<Int>
      ) -> Span<Int>.Index {
          var start = haystack.indices.startIndex
          var length = haystack.count
      
          while length > 0 {
              let half = length / 2
              let middle = haystack.indices.index(start, offsetBy: half)
              let middleValue = haystack[middle]
              if needle < middleValue {
                  length = half
              } else if needle == middleValue {
                  return middle
              } else {
                  start = haystack.indices.index(after: middle)
                  length -= half + 1
              }
          }
          return start
      }
    • 23:04 - Throughput benchmark for binary search in Span

      extension MyBinarySearchTests {
          @Test func searchSpanInt() throws {
              let span = sortedArray.span
              search(name: "Span<Int>", duration: .seconds(1)) {
                  for element in randomElements {
                      _ = binarySearchInt(needle: element, haystack: span)
                  }
              }
          }
      }
    • 26:34 - Branchless binary search

      public func binarySearchBranchless(
          needle: Int,
          haystack: Span<Int>
      ) -> Span<Int>.Index {
          var start = haystack.indices.startIndex
          var length = haystack.count
      
          while length > 0 {
              let remainder = length % 2
              length /= 2
              let middle = start &+ length
              let middleValue = haystack[middle]
              if needle > middleValue {
                  start = middle &+ remainder
              }
          }
      
          return start
      }
    • 27:20 - Throughput benchmark for branchless binary search

      extension MyBinarySearchTests {
          @Test func searchBranchless() throws {
              let span = sortedArray.span
              search(name: "Branchless", duration: .seconds(1)) {
                  for element in randomElements {
                      _ = binarySearchBranchless(needle: element, haystack: span)
                  }
              }
          }
      }
    • 29:27 - Eytzinger binary search

      public func binarySearchEytzinger(
          needle: Int,
          haystack: Span<Int>
      ) -> Span<Int>.Index {
          var start = haystack.indices.startIndex.advanced(by: 1)
          let length = haystack.count
      
          while start < length {
              let value = haystack[start]
              start *= 2
              if value < needle {
                  start += 1
              }
          }
          
          return start >> ((~start).trailingZeroBitCount + 1)
      }
    • 30:34 - Throughput benchmark for Eytzinger binary search

      struct MyBinarySearchEytzingerTests {
          let eytzingerArray: [Int]
          let randomElements: [Int]
      
          static func reorderEytzinger(_ input: [Int], array: inout [Int], sourceIndex: Int, resultIndex: Int) -> Int {
              var sourceIndex = sourceIndex
              if resultIndex < array.count {
                  sourceIndex = reorderEytzinger(input, array: &array, sourceIndex: sourceIndex, resultIndex: 2 * resultIndex)
                  array[resultIndex] = input[sourceIndex]
                  sourceIndex = reorderEytzinger(input, array: &array, sourceIndex: sourceIndex + 1, resultIndex: 2 * resultIndex + 1)
              }
              return sourceIndex
          }
      
          init() {
              let sortedArray: [Int] = (0..<arrayCount).map { _ in
                  .random(in: 0..<arrayCount)
              }.sorted()
              var eytzingerArray: [Int] = Array(repeating: 0, count: arrayCount + 1)
              _ = Self.reorderEytzinger(sortedArray, array: &eytzingerArray, sourceIndex: 0, resultIndex: 1)
              self.randomElements = (0..<searchCount).map { _ in
                  sortedArray.randomElement()!
              }
              self.eytzingerArray = eytzingerArray
          }
      
          @Test func searchEytzinger() throws {
              let span = eytzingerArray.span
              search(name: "Eytzinger", duration: .seconds(1)) {
                  for element in randomElements {
                      _ = binarySearchEytzinger(needle: element, haystack: span)
                  }
              }
          }
      }
    • 0:00 - Introdução
    • A otimização de código para CPUs com chip Apple Silicon é complexa devido às camadas de abstração entre o código-fonte do Swift e as instruções de máquina, bem como às maneiras complexas como as CPUs executam instruções fora de ordem e utilizam caches de memória. O Instruments ajuda os desenvolvedores a enfrentar essas complexidades e permite investigações de desempenho, além de analisar o desempenho do sistema para identificar o uso excessivo da CPU. Use os instrumentos Processor Trace e CPU Counters para registrar instruções, medir custos e analisar gargalos, resultando em códigos mais eficientes e melhor desempenho do app.

    • 2:28 - Mentalidade de desempenho
    • Ao investigar problemas de desempenho dos apps, é essencial ser flexível e coletar dados para validar suposições. Lentidões podem ocorrer por vários motivos: threads bloqueadas aguardando recursos, APIs usadas indevidamente ou algoritmos ineficientes. Ferramentas como o CPU Gauge, no Xcode, e System Trace e Hangs instruments, no Instruments, são inestimáveis para identificar os padrões de uso da CPU, comportamentos de bloqueio e interface não responsiva. Antes de se aprofundar nas micro-otimizações, que podem dificultar a manutenção do código, é melhor explorar abordagens alternativas. Essas alternativas incluem evitar trabalho desnecessário, atrasar esse trabalho com concorrência, pré-calcular valores e armazenar em cache o estado calculado por operações complexas. Se essas estratégias forem esgotadas, a otimização do código vinculado à CPU se tornará necessária. Concentre-se no código que afeta muito a experiência do usuário, como o caminho crítico das interações do usuário. O ideal é adotar uma abordagem de otimização incremental, acompanhando o progresso com testes automatizados e métricas de desempenho no Xcode e no Instruments.

    • 8:50 - Ferramentas de análise de desempenho
    • Para analisar o desempenho da CPU do exemplo de pesquisa binária apresentado nesta sessão, o Instruments conta com duas ferramentas de análise: o Time Profiler e o CPU Profiler. O Time Profiler faz amostragens periódicas da atividade da CPU, mas pode sofrer com aliasing, um efeito em que tarefas executadas periodicamente distorcem a representação do uso da CPU. O CPU Profiler, por outro lado, faz amostragens independentes de cada CPU com base na frequência do clock, o que o torna mais preciso e adequado para otimização de desempenho da CPU. Na análise, o instrumento CPU Profiler é escolhido e iniciado do navegador de teste do Xcode. Em seguida, a gravação no Instruments é definida como Modo Adiado para minimizar a sobrecarga. São apresentadas as áreas dentro do Instruments, entre elas, a visualização da linha do tempo, suas trilhas e faixas e a visualização detalhada dos resultados perfilados. Ao examinar as faixas Points of Interest e Process no processo "xctest", foi identificada a região específica em que as pesquisas binárias ocorrem no app de exemplo. A árvore de chamadas na visualização dos detalhes mostra que as funções relacionadas ao protocolo Collection consomem um tempo significativo da CPU. Para otimizar o desempenho, é recomendável alternar para um tipo de contêiner mais eficiente, como Span, para evitar sobrecargas associadas a Array com semântica de cópia na gravação e ao uso de genéricos.

    • 13:20 - Span
    • O Swift 6.2 introduz o Span, uma estrutura de dados otimizada no uso de memória que representa um intervalo contíguo de memória com endereço base e contagem. Usar Span para tipos de entrada e saída de pesquisa binária melhora o desempenho em 400%, sem alterar o algoritmo. Em seguida, para otimizar ainda mais o desempenho, o instrumento Processor Trace é utilizado para investigar a sobrecarga causada pela verificação de limites.

    • 14:05 - Processor Trace
    • O Instruments 16.3 introduziu um novo e importante instrumento: o Processor Trace. Essa ferramenta permite capturar um rastreamento abrangente de todas as instruções executadas pelo processo do app no espaço do usuário no Mac e iPad Pro com chip M4 ou posterior ou no iPhone com chip A18 ou posterior. O Processor Trace requer a ativação de determinados ajustes no dispositivo e é mais eficiente quando usado em sessões curtas de rastreamento, já que pode gerar uma quantidade significativa de dados. Ao registrar cada decisão de ramificação, contagem de ciclos e horário atual, o Instruments reconstrói o caminho exato de execução do app. Os dados são apresentados visualmente em um gráfico de chama, que mostra o tempo consumido por chamada de função ao longo do tempo. Diferentemente dos gráficos de chama tradicionais, que usam amostragem, o gráfico do Processor Trace fornece uma representação exata de como a CPU executou o código. Isso permite identificar gargalos de desempenho com uma precisão inédita. A análise dos dados de rastreamento revela que as sobrecargas de metadados de protocolos e a impossibilidade de aplicar inlining em comparações numéricas estão causando lentidão significativa em uma função específica de busca binária. Para resolver essa questão, a função é especializada manualmente para o tipo Int, resultando em uma melhoria substancial de desempenho de cerca de 170%. No entanto, é necessário otimizar ainda mais porque a implementação da busca binária do app continua contribuindo para a lentidão geral.

    • 19:51 - Análise de gargalos
    • As CPUs com chip Apple Silicon executam instruções em duas fases: a Entrega de Instruções e o Processamento de Instruções. Ambas as fases são executadas em pipeline para permitir o paralelismo no nível de instrução. Isso permite que várias operações sejam processadas simultaneamente, maximizando a eficiência. No entanto, gargalos podem ocorrer no pipeline, interrompendo as operações e limitando o paralelismo. O instrumento CPU Counters ajuda a identificar esses gargalos ao contar eventos em cada unidade de CPU. Ele usa modos predefinidos para medir o desempenho da CPU e dividir o trabalho em categorias amplas. Ao analisar os dados amostrados, é possível identificar instruções específicas que causam problemas, como direções de ramificação previstas incorretamente, o que pode causar o desperdício de ciclos e a degradação do desempenho. As CPUs executam instruções fora de ordem usando preditores de ramificação para melhorar o desempenho. No entanto, ramificações aleatórias podem enganar esses preditores. Como mitigação, o código é reescrito para evitar ramificações difíceis de prever, resultando em uma busca binária sem ramificações que é cerca de duas vezes mais rápida. O foco da otimização do app, então, muda para o acesso à memória, já que as CPUs utilizam uma hierarquia de caches para acelerar a recuperação de dados. O padrão de acesso do algoritmo de busca binária foi patológico para essa hierarquia, causando perdas frequentes de cache. Ao reorganizar os elementos da matriz usando um layout Eytzinger, a localidade do cache melhorou, e a busca binária ficou 200% mais rápida. Apesar dessas otimizações significativas, o código ainda enfrenta gargalo técnico no processamento de instruções. No entanto, a função de busca como um todo ficou cerca de 2.500% mais rápida, graças a diversas técnicas de profiling e micro-otimização.

    • 31:33 - Resumo
    • Ao medir e otimizar primeiro as sobrecargas de software e, então, focar nos gargalos da CPU, o desempenho do app de busca binária melhorou, resolvendo questões facilmente negligenciadas e alcançando melhor alinhamento à arquitetura da CPU.

    • 32:13 - Próximas etapas
    • Para otimizar apps, use o Instruments para coletar dados, executar testes de desempenho e analisar resultados. Também é possível conferir as sessões sobre o desempenho do Swift e ler o "Guia de Otimização para CPUs com chip Apple Silicon" na documentação para desenvolvedores. Faça perguntas ou envie seu feedback nos Fóruns para desenvolvedores.

Developer Footer

  • Vídeos
  • WWDC25
  • Otimize o desempenho da CPU com o Instruments
  • Open Menu Close Menu
    • iOS
    • iPadOS
    • macOS
    • tvOS
    • visionOS
    • watchOS
    • App Store
    Open Menu Close Menu
    • Swift
    • SwiftUI
    • Swift Playground
    • TestFlight
    • Xcode
    • Xcode Cloud
    • Icon Composer
    • SF Symbols
    Open Menu Close Menu
    • Accessibility
    • Accessories
    • Apple Intelligence
    • Audio & Video
    • Augmented Reality
    • Business
    • Design
    • Distribution
    • Education
    • Games
    • Health & Fitness
    • In-App Purchase
    • Localization
    • Maps & Location
    • Machine Learning & AI
    • Security
    • Safari & Web
    Open Menu Close Menu
    • Documentation
    • Downloads
    • Sample Code
    • Videos
    Open Menu Close Menu
    • Help Guides & Articles
    • Contact Us
    • Forums
    • Feedback & Bug Reporting
    • System Status
    Open Menu Close Menu
    • Apple Developer
    • App Store Connect
    • Certificates, IDs, & Profiles
    • Feedback Assistant
    Open Menu Close Menu
    • Apple Developer Program
    • Apple Developer Enterprise Program
    • App Store Small Business Program
    • MFi Program
    • Mini Apps Partner Program
    • News Partner Program
    • Video Partner Program
    • Security Bounty Program
    • Security Research Device Program
    Open Menu Close Menu
    • Meet with Apple
    • Apple Developer Centers
    • App Store Awards
    • Apple Design Awards
    • Apple Developer Academies
    • WWDC
    Read the latest news.
    Get the Apple Developer app.
    Copyright © 2026 Apple Inc. All rights reserved.
    Terms of Use Privacy Policy Agreements and Guidelines