Me deparei com uma questão que eu precisava usar @inlinable
e @usableFromInline
atributos que foram introduzidas no Swift 4.2 assim que eu gostaria de compartilhar minha experiência com você.
Deixe-me ir direto ao assunto, porém, nossa base de código tem um módulo de Analytics da fachada que liga outros módulos.
App Target -> módulo Analytics Fachada -> Relatórios módulo X.
Módulo Analytics Fachada tem uma função chamada report(_ rawReport: EventSerializable)
que disparar as chamadas de relatórios, esta função usa uma instância do módulo de relatórios X para enviar as chamadas de relatórios para que os relatórios específicos módulo X.
A coisa é, chamando que report(_ rawReport: EventSerializable)
funções muitas vezes para enviar as chamadas de relatórios uma vez que os usuários iniciar o aplicativo cria sobrecarga inevitável que causou uma série de acidentes para nós.
Além disso, não é uma tarefa fácil de reproduzir essas falhas se você estiver configurando o Optimisation level
para None
o modo de depuração. No meu caso eu era capaz apenas para reproduzi-lo quando eu definir o Optimisation level
para Fastest, Smalles
T ou ainda maior.
A solução foi a utilização de @inlinable
e @usableFromInline
.
Usando @inlinable
e @usableFromInline
exportar o corpo de uma função como parte da interface de um módulo, tornando-o disponível para o otimizador quando referenciado a partir de outros módulos.
O @usableFromInline
atributo marca uma declaração interna como sendo parte da interface binária de um módulo, permitindo que ele seja usado de @inlinable
código sem expô-lo como parte da interface de origem do módulo.
Através dos limites do módulo, os genéricos de tempo de execução introduzir sobrecarga inevitável, como tipo reified metadados deve ser passada entre as funções, e vários padrões de acesso indirecto deve ser utilizado para manipular os valores de tipo genérico. Para a maioria das aplicações, essa sobrecarga é insignificante em comparação com o trabalho real executado pelo próprio código.
Um cliente binário construído contra esse quadro pode chamar essas funções de genéricos e desfrutar de uma possível melhora o desempenho quando construído com otimizações habilitadas, devido à eliminação de sobrecarga abstração.
Código de amostra:
@inlinable public func allEqual<T>(_ seq: T) -> Bool
where T : Sequence, T.Element : Equatable {
var iter = seq.makeIterator()
guard let first = iter.next() else { return true }
func rec(_ iter: inout T.Iterator) -> Bool {
guard let next = iter.next() else { return true }
return next == first && rec(&iter)
}
return rec(&iter)
}
Mais informações - Cross-módulo inlining e especialização