04 ago. 2025

Performance no IOS: Entendendo Dynamic Dispatch e Static Dispatch

O que é Dispatch?
gft-contact-renan-carneiro.png
Renan Carneiro
Especialista Mobile - PSU BR
blogAbstractMinutes
blogAbstractTimeReading
gft-image-mood-10.jpg
Transformação Digital
Terça Tech
contact
share
No Swift, existem duas formas principais de dispatch:
  •  Static Dispatch (Despacho Estático): A decisão de qual método executar é feita em tempo de compilação.

 

  •  Dynamic Dispatch (Despacho Dinâmico): A decisão é adiada para o tempo de execução, o que permite maior flexibilidade, porém com um pequeno custo de performance.

Static Dispatch

No Static Dispatch, o compilador sabe exatamente qual método será chamado durante a compilação. Isso permite que ele realize otimizações como o inlining, que consiste em substituir a chamada de uma função pelo seu próprio código, eliminando a sobrecarga da chamada e melhorando o desempenho.

 

Características:

  •  Decidido em tempo de compilação.

 

  •  Sem custo de lookup (busca dinâmica em tempo de execução).

 

  •  Melhor performance.

 

  •  Não permite sobrescrita (overriding) de métodos.

 

Quando ocorre:

 

  • Métodos marcados como final (não podem ser sobrescritos).

 

  •  Métodos em structs e enums (tipos por valor).

 

  •  Funções static.

 

  •  Métodos de classes marcados como final.

Dynamic Dispatch

Já no Dynamic Dispatch, a decisão sobre qual método será executado acontece em tempo de execução, com base no tipo real do objeto. Isso permite polimorfismo, ou seja, que subclasses sobrescrevam métodos da superclasse e que o comportamento mude conforme a instância usada.

 

Para realizar essa decisão, o sistema utiliza estruturas como a dispatch table (ou vtable, "virtual method table") — uma tabela interna que armazena ponteiros para os métodos que podem ser chamados dinamicamente. Quando um método é invocado, o sistema faz um lookup (busca) nessa tabela para descobrir qual versão do método deve ser executada.

 

Características:

 

  • Decidido em tempo de execução.

 

  •  Permite sobrescrita de métodos.

 

  •  Pequeno custo de lookup na dispatch table/vtable.

 

  •  Suporte ao polimorfismo e runtime dinâmico.

 

Quando ocorre:

 

  • Métodos de classes não marcados como final.

 

  •  Métodos marcados com @objc.

 

  •  Métodos declarados como dynamic.

O que são @objc e dynamic?

 

  • @objc: Indica que o método ou propriedade pode ser acessado pelo runtime do Objective-C. Isso é necessário quando você precisa de compatibilidade com APIs escritas em Objective-C ou quando usa mecanismos como Selector, notificações (NotificationCenter) ou KVO (Key-Value Observing).

 

  • dynamic: Informa explicitamente que o método deve usar dynamic dispatch, mesmo em um contexto onde o Swift usaria dispatch estático. Todo método dynamic também é @objc automaticamente.

 

Selector: Um selector é uma forma de referenciar métodos por nome (como uma string) no runtime do Objective-C. É amplamente usado para chamadas dinâmicas, como no performSelector, target-action e observadores.

 

Exemplo prático:

 

 

again.png

Como saber se é Dynamic ou Static Dispatch?

Uma forma rápida de saber:

tech1.png

Comparação de Performance Benchmark Simples:

import Foundation

class DynamicClass {                                                                                              

         func compute() -> Int {

       return 42

            }

 }

 final class StaticClass {

            func compute() -> Int {

         return 42 }

 }

 struct StaticStruct {

             func compute() -> Int {

          return 42 }

 }

 func measure( label: String, block: ()-> Void) {

          let start CFAbsoluteTimeGetCurrent()

          block()

          let diff CFAbsoluteTimeGetCurrent() start

          print("\(label) took \(diff) seconds")

 }

 let dynamic DynamicClass()

 let staticStruct = StaticStruct()

let staticClass StaticClass()

 

let iterations = 1_000_000

 

measure("Dynamic Dispatch") {

            var result = 0

            for in 0..<iterations {

                       result += dynamic.compute()

            }

 assert(result > 0)

}

 

measure("Static Dispatch (final class)") {

             var result = 0

             for } in 0..citerations {

                         result += staticClass.compute()

                 }

            assert(result > 0)

 

measure("Static Dispatch (struct)”) {

            var result =0

            for _ in 0 ..siterations ( for result = staticStruct.compute()

                   }

              assert(result > 0)

}

Resultados esperados:

  • Static Dispatch: geralmente de 10% a 30% mais rápido dependendo do ambiente.

 

  • Dynamic Dispatch: pequeno overhead devido ao lookup na vtable.

Quando se preocupar?

Deve-se considerar static dispatch em código de alto desempenho, como:

 

  • Processamento gráfico.

 

  • Algoritmos de machine learning no device.

 

  • Processamento de áudio em tempo real.

 

  •  Uso de “final” não só melhora a performance, mas também expressa intenção de design (prevenção de herança).

Conclusão

O Dynamic Dispatch oferece flexibilidade e suporte ao polimorfismo — essencial na programação orientada a objetos. Por outro lado, o Static Dispatch proporciona máxima performance, sendo favorecido em cenários com struct, enum, métodos static ou final.

 

Entender como e quando cada tipo de dispatch ocorre não só ajuda a otimizar a performance da sua aplicação, como também contribui para um design mais claro, robusto e seguro.

 

No Swift, equilibrar o uso de value types (como structs) e reference types (classes) vai além da modelagem de dados: impacta diretamente o desempenho da aplicação.

 

 

 

Danielle Lopes

gft-br-contact-danielle-lopes-2.png
Sua especialista | Marketing
Diretora de Marketing e Comunicação LATAM GFT
message
dataProtectionDeclaration