Runtime: Pesquisa: AOT nativo

Criado em 6 ago. 2020  ·  55Comentários  ·  Fonte: dotnet/runtime

O desempenho tem sido um recurso chave do .NET. As opções existentes para otimizar aplicativos publicados funcionam bem para a maioria dos cenários que o .NET visa hoje.

Alguns de vocês nos pediram para considerar a adição de uma opção de compilação AOT nativa com características distintamente diferentes. As características distintamente diferentes da AOT nativa vêm com compensações, como menor compatibilidade, que são explicadas em detalhes em .NET Runtime Form Factors . Criamos uma pesquisa para nos ajudar a entender melhor os casos de uso nativos de AOT.

Agradecemos o seu feedback para que possamos trabalhar na criação dos planos certos para o futuro. Se você não fornecer detalhes de contato, as respostas serão anônimas.

Pesquisa: https://www.surveymonkey.com/r/7THQK5K

Obrigado pelo seu tempo!

area-Meta

Comentários muito úteis

As opções existentes para otimizar aplicativos publicados funcionam bem para a maioria dos cenários que o .NET visa hoje.

...

AOT importa principalmente em aplicativos GUI. É aí que ele precisa de foco. Não vejo webapp, serviços etc. precisando disso

Discordo. Para o melhor UX do usuário final, AOT com link estático é necessário para mecanismos de jogos , microsserviços sem servidor , aplicativos GUI de desktop, aplicativos iOS e Android , SPAs/bibliotecas do lado do cliente baseados em WASM e ferramentas CLI básicas (~ poucos MBs).

Eu gostaria de poder compilar facilmente meu código AOT enquanto experimentava todos os cenários acima em C# nos últimos anos e sinto que .NET está perdendo muito em comparação com linguagens baseadas em LLVM como Rust.

A razão pela qual as opções de publicação atuais parecem "funcionar bem" é porque .NET historicamente não tem sido adequado para os cenários acima e as pessoas apenas implementam sua própria AOT (por exemplo: Unity, UWP, Mono) ao usar C#. Soluções AOT parciais como como imagem nativa (por exemplo, ReadyToRun) pode "ajudar" em cenários de inicialização a frio para aplicativos de servidor monolíticos ou grandes aplicativos clientes de desktop, mas o tamanho binário ainda é muitas vezes maior do que um tempo de execução AOT completo produziria.

O .NET já não "funciona bem" para microsserviços sem servidor/contêiner - eles podem se beneficiar muito da compilação AOT, tamanho binário reduzido e dependências mínimas .
A solução atual ReadyToRun + Tiered Compilation + IL Linker já atingiu um limite para o tamanho do arquivo que é irritante para implantações independentes, como a recomendada pelo AWS Lambda em sua postagem no blog.

O verdadeiro problema é que atualmente existem muitos runtimes/geradores de código/toolchains/experiments disponíveis com suas próprias peculiaridades: IL2CPP/Burst (Unity), backend AOT do Mono (Xamarin/Blazor/Uno), .NET Native/CoreRT (UWP), O backend LLVM do Mono, CrossGen/ReadyToRun (.NET Core), etc. e é simplesmente inaceitável que o .NET não tenha uma cadeia de ferramentas de compilação AOT padronizada.

Se todas essas equipes combinassem seus esforços de engenharia em algo comum, como CoreRT, backend Mono LLVM ou o agora abandonado dotnet/lilic , então AOT teria sido uma experiência muito melhor para desenvolvedores .NET.

AOT com link estático é acessível a um grande número de desenvolvedores agora com CI/CD para as massas e não é mais apenas um incômodo para um aumento marginal no desempenho.

Endgame C#: Código nativo, UI nativa, interoperabilidade rápida e fácil, exportações nativas e APIs orientadas ao desempenho (por exemplo, System.IO.Pipelines, System.Text.Json).

Todos 55 comentários

Não consegui descobrir o melhor rótulo de área para adicionar a esse problema. Se você tiver permissões de gravação, ajude-me a aprender adicionando exatamente um rótulo de área .

Parece um erro de digitação - * 9. Which of these tasks are apart of your production debugging workflow? (Please select all that apply) Talvez devesse ser "uma parte de"?

Estou muito feliz em ver este problema! 😄🚀

Pergunta: para desenvolvedores UWP que trabalharam com a cadeia de ferramentas .NET Native, devemos responder à pesquisa apenas dizendo que não usamos o CoreRT antes, ou uma vez que o .NET Native tem muitas semelhanças (e alguns códigos compartilhados também?) apenas mencionamos isso nas notas e, em seguida, respondemos às outras perguntas do CoreRT apenas com relação à nossa experiência com o .NET Native? 🤔

@Sergio0694 obrigado pela pergunta UWP. Concordo, acho que faz sentido mencionar isso nas notas e responder ao uso corert se você usou a versão de código aberto.

Obrigado por postar esta pesquisa!

Eu também estava confuso sobre como responder a certas perguntas como um desenvolvedor UWP que usou apenas .NET Native. Tenho várias opiniões sobre a cadeia de ferramentas .NET Native da UWP, mas realmente não vi um lugar para escrevê-las. Tudo bem se isso estiver fora do escopo desta pesquisa, mas pode valer a pena esclarecer.

Também suspeito que "porque .NET Native é o padrão para compilações de versão UWP e necessário na Loja" é provavelmente o motivo mais comum pelo qual as pessoas usam AOT, mas não é uma das respostas pré-preenchidas para a pergunta 5.

Obrigado por incluir o Avalonia nas opções de GUI :) Nós experimentamos com CoreRT+Avalonia antes e os resultados foram lindos aplicativos de GUI nativos :D embora não tenhamos mantido a compatibilidade desde então...

Uma parte muitas vezes esquecida do .net é o desenvolvimento de jogos, muitas plataformas não permitem que um JIT seja executado, pense em Consoles ou dispositivos IOS.
É muito importante para o futuro do desenvolvimento de jogos obter AOT nativo do .net como um cidadão de primeira classe do ecossistema .net.
Alguns mecanismos de jogos lançaram seu próprio AOT (por exemplo, o Unity faz com il2cpp), mas é um desastre absoluto.
Portanto, uma solução oficial seria mais do que bem-vinda. Poderia ser um evento de mudança da indústria.
Não se esqueça de que a indústria de jogos está ultrapassando a indústria cinematográfica em lucro e volume de negócios.
Consoles é onde o lucro principal está sendo feito.

As opções existentes para otimizar aplicativos publicados funcionam bem para a maioria dos cenários que o .NET visa hoje.

...

AOT importa principalmente em aplicativos GUI. É aí que ele precisa de foco. Não vejo webapp, serviços etc. precisando disso

Discordo. Para o melhor UX do usuário final, AOT com link estático é necessário para mecanismos de jogos , microsserviços sem servidor , aplicativos GUI de desktop, aplicativos iOS e Android , SPAs/bibliotecas do lado do cliente baseados em WASM e ferramentas CLI básicas (~ poucos MBs).

Eu gostaria de poder compilar facilmente meu código AOT enquanto experimentava todos os cenários acima em C# nos últimos anos e sinto que .NET está perdendo muito em comparação com linguagens baseadas em LLVM como Rust.

A razão pela qual as opções de publicação atuais parecem "funcionar bem" é porque .NET historicamente não tem sido adequado para os cenários acima e as pessoas apenas implementam sua própria AOT (por exemplo: Unity, UWP, Mono) ao usar C#. Soluções AOT parciais como como imagem nativa (por exemplo, ReadyToRun) pode "ajudar" em cenários de inicialização a frio para aplicativos de servidor monolíticos ou grandes aplicativos clientes de desktop, mas o tamanho binário ainda é muitas vezes maior do que um tempo de execução AOT completo produziria.

O .NET já não "funciona bem" para microsserviços sem servidor/contêiner - eles podem se beneficiar muito da compilação AOT, tamanho binário reduzido e dependências mínimas .
A solução atual ReadyToRun + Tiered Compilation + IL Linker já atingiu um limite para o tamanho do arquivo que é irritante para implantações independentes, como a recomendada pelo AWS Lambda em sua postagem no blog.

O verdadeiro problema é que atualmente existem muitos runtimes/geradores de código/toolchains/experiments disponíveis com suas próprias peculiaridades: IL2CPP/Burst (Unity), backend AOT do Mono (Xamarin/Blazor/Uno), .NET Native/CoreRT (UWP), O backend LLVM do Mono, CrossGen/ReadyToRun (.NET Core), etc. e é simplesmente inaceitável que o .NET não tenha uma cadeia de ferramentas de compilação AOT padronizada.

Se todas essas equipes combinassem seus esforços de engenharia em algo comum, como CoreRT, backend Mono LLVM ou o agora abandonado dotnet/lilic , então AOT teria sido uma experiência muito melhor para desenvolvedores .NET.

AOT com link estático é acessível a um grande número de desenvolvedores agora com CI/CD para as massas e não é mais apenas um incômodo para um aumento marginal no desempenho.

Endgame C#: Código nativo, UI nativa, interoperabilidade rápida e fácil, exportações nativas e APIs orientadas ao desempenho (por exemplo, System.IO.Pipelines, System.Text.Json).

Discordo da afirmação de que os webapps não se beneficiariam com isso. AOT ajudaria muito com cargas de trabalho sem servidor (também conhecidas como Azure Functions). Sem mencionar os benefícios do tempo de inicialização das ferramentas CLI.

Respondi à pesquisa, mas para ser honesto, não recebo essa pergunta contínua de pesquisas desde o início do .NET Core 1.0, sem uma direção clara para onde as coisas estão indo.

.NET Native é o que .NET deveria ter sido o tempo todo, quando o projeto Ext-VOS começou, e há a experiência de Singularity e Midori com a qual vocês certamente podem se relacionar, ou até mesmo obter alguns servidores internos com eles.

Mesmo o Java decidiu recuperar seus recursos AOT ausentes, a equipe não está perguntando quais cargas de trabalho queremos que funcionem.

Dificilmente usamos NGEN, porque desde o lançamento do .NET sua geração de qualidade de código nunca foi melhorada e o fluxo de trabalho de implantação é uma dor em relação a outras linguagens compiladas AOT.

Portanto, se daqui para frente, o AOT for retirado novamente do .NET, considere que toda a concorrência em linguagens gerenciadas agora está focando em cadeias de ferramentas AOT, e eles também não perguntam quais fluxos de trabalho gostaríamos de usar o compilador.

Eu quero ver o .NET continuando a florescer e sendo a primeira opção independentemente do cenário, e se alguma coisa para assumir fluxos de trabalho onde a Microsoft ainda nos força a usar C++ junto com .NET, com o qual outras linguagens compiladas AOT não têm problemas.

Respondi à pesquisa, mas para ser honesto, não recebo essa pergunta contínua de pesquisas desde o início do .NET Core 1.0, sem uma direção clara para onde as coisas estão indo.

Acho ótimo que a MS esteja tentando ouvir a comunidade, em vez de apenas ditar o que queremos.

@jkotas Percebi que dois links diferentes para esta pesquisa estão se espalhando, tudo bem?
https://www.surveymonkey.com/r/7THQK5K
https://www.surveymonkey.com/r/SQV8JQK

@texasbruce pergunte aos colegas desenvolvedores que responderam a pesquisas semelhantes sobre suporte a ferramentas de interface gráfica, WCF e EF de plataforma cruzada o quanto isso ajudou.

Então, embora seja bom que eles nos perguntem, seria melhor quando as ações realmente acontecessem. Mesmo para a interface gráfica de plataforma cruzada, resta saber se o MAUI realmente acontecerá ou se o Blazor nos Web Widgets é empurrado como solução.

Para mim, a única solução AOT aceitável é quando ela gera um aplicativo nativo verdadeiro sem JIT no modo de lançamento (sem alias de solução lado a lado pronto para ser executado) e quando funciona em todos os projetos¹ .NET que os desenvolvedores estão trabalhando sobre. Isso inclui especificamente Winforms e WPF. Na melhor das hipóteses, ele também deve funcionar de forma independente, sem dependências de tempo de execução, sem aumentar de 3 MB para 80 MB.

¹ Por motivos técnicos, pode haver casos/apis que a AOT não pode suportar. Dizer "em todos" significa não oferecer suporte a todas as APIs, mas a todos os tipos de projeto. O .NET Core suporta: dll / winforms / wpf / winui / console / maui / ... Algo semelhante a mudar de .NET Framework para .NET Core, que permitia a maioria desenvolvedores para assumir seus aplicativos existentes é o que tenho em mente.

_Eu também escrevi aplicativos em Delphi e isso me incomoda ver que eu apenas compilo e depois envio meu único executável Delphi para outro lugar e ele simplesmente roda. E é apenas mais rápido. O mesmo se aplica a um aplicativo C++ quando compilado de uma maneira específica. E você ainda pode depurar ambos os aplicativos e ambos os aplicativos ainda fornecem um stacktrace/dump útil quando você decide incluir o PDB. Mas, por razões de segurança, você também pode decidir NÃO incluí-lo, o que também funciona bem. Incomoda-me perguntar a mim mesmo por que não podemos ter isso com C#? Quando ouvi falar dos planos AOT eu esperava ISSO._

Eu sempre vejo problemas com reflexão muito mencionados, e acredito que na verdade não importa muito se o núcleo do ASP.net produz um grande executável.

A maioria dos lugares onde o AOT é um requisito difícil são coisas como ferramentas CLI, jogos e aplicativos de interface do usuário, eles podem ser exigentes sobre quais bibliotecas incluir e podem evitar alguns problemas de reflexão. A prioridade deve ser habilitar aplicativos "limpos".

Eu sempre vejo problemas com reflexão muito mencionados, e acredito que na verdade não importa muito se o núcleo do ASP.net produz um grande executável.

Com o lançamento do Blazor WebAssembly, acho que o tamanho do executável e também a velocidade de execução serão muito importantes e podem se beneficiar muito do AOT. Mas, por qualquer motivo, nem foi mencionado especificamente na pesquisa.

Sim, linda por favor! Eu estava pensando em usar Rust ou CoreRT para manter a segurança da memória e ganhar velocidades nativas e fazer com que meu código pudesse ser chamado nativo. Mas seria fantástico ter AOT em .NET, pois é incrivelmente rico e poderoso e Rust, embora fantástico, não é fácil de fazer a transição.

@jkotas Percebi que dois links diferentes para esta pesquisa estão se espalhando, tudo bem?

Sim, usamos links diferentes da SurveyMonkey para postagens diferentes. Todos os links apontam para a mesma pesquisa. Ele nos permite ver como a distribuição das respostas varia dependendo de onde as pessoas encontraram a pesquisa.

Para gamedev, precisamos disso, suspendi o trabalho no meu mecanismo de jogo https://github.com/amerkoleci/alimer_sharp em favor do mecanismo nativo usando c++, mantenho ligações para DirectX e vulkan também, é necessário desempenho aqui

Para gamedev, precisamos disso, suspendi o trabalho no meu mecanismo de jogo https://github.com/amerkoleci/alimer_sharp em favor do mecanismo nativo usando c++, mantenho ligações para DirectX e vulkan também, é necessário desempenho aqui

Cenário idêntico aqui 😄, só que não suspendi . Eu gosto de AOT tanto pelos melhores tempos de inicialização, mas também (e no meu caso, mais importante), pela oportunidade de ter um código mais otimizado - estou bem com um aumento de 50% nos tempos de compilação para uma aceleração de 10%, o que obviamente não é t realmente a atitude de um JIT

Estou bem com um aumento de 50% nos tempos de construção para uma aceleração de 10%, o que obviamente não é realmente a atitude de um JIT

Esta é realmente uma das grandes razões secundárias que eu quero AOT em .NET em vez de mudar para um ecossistema diferente. Estou totalmente estragado pelos tempos de compilação rápidos de grandes projetos .NET em comparação com grandes projetos C++ ou Rust.

Eu quero JIT para a iteração rápida durante o desenvolvimento, mas AOT quando estiver enviando algo para meus clientes.

Eu usei CoreRT para criar bibliotecas nativas de plataforma cruzada (e plataforma cruzada).

AOT com link estático é urgentemente necessário para mecanismos de jogos no iOS e plataformas de console que desativam o jit e também desejam vários modos de compilação aot:

  1. aot completo
  2. aot híbrido que suporta jit + aot ou intérprete + modo de execução aot
    aot híbrido é realmente importante para a indústria de jogos, pode ser um divisor de águas

AOT com link estático é urgentemente necessário para mecanismos de jogos no iOS e plataformas de console que desativam o jit e também desejam vários modos de compilação aot:

  1. aot completo
  2. aot híbrido que suporta jit + aot ou intérprete + modo de execução aot
    aot híbrido é realmente importante para a indústria de jogos, pode ser um divisor de águas

como mono na plataforma iOS, modo de execução aot + intérprete.

Aot completo, exe único, tempo de execução independente e recorte de códigos desnecessários, definitivamente me deixa kreygasm XD

Estou esperando por essa pergunta há 10 anos. Porra, eu tenho 5 projetos legais que estão acumulando poeira no disco rígido, porque se eu liberá-los, qualquer criança pode revertê-los, adicionar pequenas alterações à GUI e vendê-los como seus.

Desenvolvi Robocraft, Cardlife e Gamecraft com Unity na plataforma PC e nunca precisei usar IL2CPP, a não ser que fosse necessário (leia Xbox one), nem mesmo para os servidores do jogo. Eu pessoalmente veria uma mistura de compilação JIT e uma solução como Burst (que faz um trabalho melhor do que eu poderia fazer usando intrínsecos explícitos) como mais do que suficiente quando o desempenho é necessário. No entanto, entendo que o AOT é necessário para as plataformas que exigem código totalmente nativo e para as plataformas em que os recursos de hardware são preciosos. Eu entendo como os desenvolvedores da plataforma .net podem ter sentimentos contraditórios sobre AOT, mas não acho que seja uma opção se quisermos que ela seja adotada de forma mais ampla no desenvolvimento de jogos. Para ser honesto, me assusta um pouco que Unity tenha o monopólio de tecnologias como IL2CPP e Burst.

Desenvolvemos simuladores financeiros/científicos de alto desempenho e alta escalabilidade. Nossas simulações podem ser executadas de alguns minutos a muitos dias, dependendo da complexidade do modelo que o usuário cria.

Devido à natureza do nosso software de simulação, os tempos de inicialização quase nunca são uma preocupação, assim como os tamanhos de software/binário. Aliás, nem o tempo que leva para instalar o produto. Por exemplo, seria completamente aceitável para nós, se a compilação fosse parte da instalação, mesmo que esse processo demorasse muito.

Eu diria que cerca de 25% do código durante uma execução é criado dinamicamente, então uma abordagem híbrida seria preferida; alguma combinação de compilação AOT e JIT. Se os bits dinâmicos tivessem que ser interpretados, acho que muitos dos benefícios do AOT seriam diminuídos, pelo menos em nosso caso de uso.

O GC é nosso problema número um nos impedindo de alcançar uma escalabilidade maior (por exemplo, quando chegarmos a cerca de 44 núcleos). Ter o compilador capaz de fazer otimizações inter-assembly mais aprofundadas, in-lining agressivo e análise de escape pode permitir que mais objetos de vida curta sejam alocados na pilha em vez do heap.

Há muitos lugares em nossa base de código onde a qualidade do código JIT se torna um gargalo, particularmente com alocações de registradores e lidar com muitas estruturas. Isso nos força a escrever código para manipular o compilador JIT para fazer a coisa certa (um cabo de guerra que é frágil, ofuscante e difícil de manter) ou cair no código nativo (e perdemos muito do benefício da falta de inlining e sobrecarga das transições GC/PInvoke).

Às vezes, pequenas melhorias na qualidade do código podem gerar ganhos insanos ao longo de um modelo que é executado por horas em vários núcleos. Para nós, o JIT se tornou um pouco frágil (ainda menos determinista) com o desempenho, pois nossa base de código muda com o desenvolvimento. Nossa esperança seria que um compilador AOT pudesse levar muito mais tempo para compilar e gerar código de qualidade muito mais alta, reduzindo algumas dessas flutuações de desempenho desnecessárias e nos permitindo manter mais de nossa base de código em C#.

Em geral, eu adoraria ver mais investimentos em tecnologias JIT e AOT.

cc @AndyAyersMS

AOT com link estático é urgentemente necessário para mecanismos de jogos no iOS e plataforma de console que desativam o jit,

Concordo totalmente aqui. Como precisamos de uma solução para esse problema (código C# rodando em consoles de jogos para um projeto não Unity), estamos usando uma cadeia de ferramentas baseada em Mono-AOT. Mas tem algumas limitações sérias e não funciona tão bem.

Portanto, estamos tentando fazer o CoreRT rodar em 3 consoles de álamo (XBox One; PlayStation 4 e Nintendo Switch). Um teste inicial de conceito mostra que ele realmente funciona (ainda com algumas limitações), mas já com uma melhoria significativa no desempenho do tempo de execução em comparação com a solução baseada em Mono.

Mas com a situação do NDA em torno dos consoles de jogos, o suporte oficial para essa causa de uso é ainda mais improvável do que obter o AOT nativo oficial em primeiro lugar.

Para nós, o JIT se tornou um pouco frágil (ainda menos determinista) com o desempenho, pois nossa base de código muda com o desenvolvimento.

@jpapp05 Eu adoraria ouvir mais sobre seu aplicativo e o problema acima especificamente, pois é uma das minhas principais preocupações. Sinta-se à vontade para entrar em contato comigo offline (via e-mail no perfil) se isso ajudar.

Oi @AndyAyersMS , isso seria ótimo. Entrarei em contato com você offline, pois posso falar um pouco mais livremente, mas ficarei feliz em postar qualquer resumo de nossas discussões para o benefício de outras pessoas.

Não sei se isso é mesmo um problema, mas apenas para mencionar aqui.
Um recurso importante para nós seria a capacidade de carregar e descarregar dinamicamente assemblies nativos em tempo de execução.

Meu maior problema é que normalmente o .NET pode ser facilmente descompilado, exceto com UWP Native, pelo menos até onde eu testei (espero estar certo). Não em uma mentalidade de empresa "normal", alguém colocará muito IP em um projeto que pode ser facilmente descompilado.
Linux é legal ok, mas todos os aplicativos de desktop são para Windows no mundo corporativo.

Talvez para facilitar a vida, coloque uma caixa de seleção que diga:
COMPILAÇÃO NATIVA (FUNCIONA SOMENTE PARA WINDOWS 10 DESKTOP!)
Cara, faça isso e eu não me importo mais com AOT. Se funcionar para ASP.NET Core, legal! Se não, eu realmente não me importo.

A propósito, obrigado por criar a questão perguntando e fazer a pesquisa, você fez um ótimo trabalho porque está pedindo a opinião de pessoas que usam a tecnologia em seus trabalhos. Eu acho (na verdade, tenho certeza) que você ainda sente falta de muitas opiniões de desenvolvedores de desktop que geralmente não se envolvem nessas coisas no Github. Nem todo mundo se lembra (ou sabe) que o código .NET pode ser facilmente descompilado e tenho certeza que seus chefes ficariam loucos se soubessem : grin:.

Nem todo mundo lembra (ou sabe) que o código .NET pode ser facilmente descompilado

Shhh... O fato de o Rider fazer isso para você automaticamente é incrível quando estou tentando descobrir como algo funciona nos bastidores no Unity ou em pacotes de terceiros. Não é tão importante agora, porém, com muito do código sendo de código aberto em primeiro lugar, mas você entende o que quero dizer.

@jcbeppler Você está errado, esse é um mal-entendido comum de bytecode versus nativo, é apenas uma questão de ter as ferramentas certas.

https://www.hex-rays.com/products/decompiler/compare/compare_vs_disassembly/

Hex-Rays é apenas uma solução possível, existem outras para escolher.

@MostHated Sim, entendi. Na verdade, é tão simples descompilar um software em .NET que é como se fosse de código aberto e muitas empresas não querem que seu software seja de código aberto. "Não existe almoço grátis" 😄

@pjmlp Eu sei a diferença entre descompilar e desmontar. Não posso fazer nada contra a desmontagem do meu software, mas a compilação nativa pode tornar o software muito mais seguro porque a pessoa não pode fazer uma descompilação muito simples. Um software desmontado definitivamente parecerá estranho e o código desmontado pode nem funcionar corretamente.

@jcbeppler Você está errado, esse é um mal-entendido comum de bytecode versus nativo, é apenas uma questão de ter as ferramentas certas.

Atualmente um programa .NET descompilado revela todo o código fonte. Isso inclui até mesmo todos os nomes de métodos e nomes de variáveis. Isso é legal para depuração e nos permite ter um rastreamento de pilha "legível" quando ocorre uma exceção. No entanto, é uma enorme falha de segurança e uma razão pela qual existe um enorme mercado para ofuscadores .NET.

Um aplicativo nativo pode ser desmontado. Mas ele não revela seu código fonte completo em C++/Delphi etc. (existem algumas ferramentas que tentam reconstruir este código fonte, mas os resultados são horríveis). O que você obtém é, no máximo, código assembler e fluxogramas de controle. Se você tiver sorte e ele for fornecido com o arquivo de símbolos, você também obterá os nomes das funções, mas no modo de liberação, esse arquivo de símbolos geralmente não é incluído, novamente por motivos de segurança.

Podemos nos perder em detalhes falando sobre como o código nativo é uma proteção real. Na minha opinião, não é uma proteção em termos de cracking (embora, graças aos nomes completos de métodos / variáveis ​​​​e à geração completa de fonte C#, uma verificação de licença pode ser removida sem exigir nenhum conhecimento especial) ou depuração, mas uma proteção contra ladrões. Ferramentas como o dnSpy podem até exportar o aplicativo .NET para um projeto VS completo com um ÚNICO CLIQUE. Não existe tal ferramenta que funcione da mesma maneira para código nativo. Então para aplicações comerciais seria uma grande vitória gerar código nativo, além do fato de não precisarem mais pagar milhares de dólares por ano por algo que apenas renomeia todos os métodos e variáveis ​​na aplicação final.

Estou curioso sobre o resultado desta pesquisa. Existem planos para torná-los públicos sobre como as pessoas votaram?

@Symbai Não é uma proteção contra nada, como qualquer desenvolvedor Android que tentou usar o NDK como meio de proteger seu IP lhe dirá. Os aplicativos que você menciona brevemente podem fazer o mesmo com um único clique e, embora geralmente assumam código C ou C++ como código-fonte original, são bons o suficiente para roubar seus algoritmos.

Eu quero AOT, para cenários em que o .NET perderá a longo prazo contra Rust, Go, Swift, C++, Java (GraalVM), desktop, console e aplicativos móveis/IoT onde o tempo de inicialização é realmente importante, há grandes restrições no uso de memória e a perda de velocidade devido ao JIT na carga do Assembly não é tolerável, assim como em alguns cenários ASP.NET, o código AOT pode ser relevante quando alguém está dimensionando suas instâncias de pods de 100 K8S.

Por outro lado, também acho relevante manter as capacidades do JIT, e melhorá-las também, em cenários onde o JIT é o caminho a seguir.

Existem muitas linguagens que oferecem ambos os modelos de compilação, permitindo que seus usuários escolham dependendo da situação, então basicamente vamos manter o JIT por perto e melhorar a história do AOT na direção do .NET Native, esquecendo a tímida tentativa chamada NGEN.

@Symbai Não é uma proteção contra nada, como qualquer desenvolvedor Android que tentou usar o NDK como meio de proteger seu IP lhe dirá. Os aplicativos que você menciona brevemente podem fazer o mesmo com um único clique e, embora geralmente assumam código C ou C++ como código-fonte original, são bons o suficiente para roubar seus algoritmos.

Roubar um algoritmo com o qual posso conviver, mas não o que o .NET permite hoje (por exemplo, WPF), onde uma pessoa tem seu aplicativo completo lindamente e facilmente pronto para ser executado como um projeto VS. Acho que o UWP com compilação nativa faz um bom trabalho, se alguém quiser desmontá-lo, ok, boa sorte! Eu sempre usarei a compilação nativa, não importa o quê. Mundo Android do qual não posso falar, tentei AOT com Xamarin Forms uma vez e realmente não funcionou como eu esperava.

Acho que o UWP com compilação nativa faz um bom trabalho, se alguém quiser desmontá-lo, ok, boa sorte! Eu sempre usarei a compilação nativa, não importa o quê. Mundo Android do qual não posso falar, tentei AOT com Xamarin Forms uma vez e realmente não funcionou como eu esperava.

Spoiler - as pessoas que estão tentando chegar à sua fonte provavelmente estão tentando melhorar/estender/integrar com você, não enganá-lo. Se eles estão tentando enganar você, então suas métricas são realmente tolas.

Se eu escrever um livro, então peça a alguém para traduzi-lo para o japonês antes de publicá-lo - eu posso pensar que sou muito inteligente, porque não entendo japonês, nem meus amigos. A realidade é que existem países inteiros por aí que podem ler esse livro - e eu não estou fazendo nada além de me enganar se fingir o contrário.

Digo isso como um desenvolvedor que não tinha experiência com binários nativos desmontados e decidiu fazer engenharia reversa da criptografia e dos formatos de dados no Star Citizen.

Levei, alguém com zero experiência anterior, duas semanas para ir do nada, para ter um programa que pode não apenas descriptografar seus arquivos de dados criptografados, mas também converter seus formatos de dados proprietários em XML/JSON.

Após essas 2 semanas - talvez eu não tenha seu aplicativo completo pronto para ser executado como um projeto VS - mas também percebo que não preciso. É muito mais simples apenas injetar meu próprio código no aplicativo existente e não ter que lidar com todo o código deles.

ter um programa que pode não apenas descriptografar seus arquivos de dados criptografados

A criptografia é algo completamente diferente. Descompilar um VIDEO GAME para criar mods é algo completamente diferente. A maioria dos desenvolvedores de jogos não se importa se seus fãs criam mods, mas sim mostra sua paixão e amor pelo jogo. E talvez a "criptografia" não fosse uma criptografia, mas os arquivos eram apenas compactados para um tamanho menor? Por não ter que armazenar milhares de arquivos únicos em disco. O desempenho também pode ter sido um motivo... ler muitos arquivos pequenos do disco é mais lento do que ler um arquivo enorme. E depois de 2 semanas você conseguiu descompactar as imagens compactadas. Você conseguiu alterar o texto em alguns arquivos de dados. Isso é ótimo, mas não é a razão pela qual pessoas como eu querem se livrar do JIT.

O problema que temos agora é que o código JIT pode ser totalmente descompilado para completar o código-fonte, Java tem o mesmo problema, assim como qualquer outra linguagem JIT. O código nativo pode ser desmontado (isso transformará o código da máquina em código assembly), os aplicativos nativos podem ser quebrados com recursos suficientes, tudo isso é verdade, mas o código nativo não pode ser compilado para completar o código-fonte. Você já viu uma ferramenta como dnSpy para código C++? Código Delphi? eu não tenho. É porque não é possível obter nomes de variáveis ​​e métodos, eles simplesmente não existem mais quando compilados corretamente. Não é possível transformar a desmontagem em C++ e gerar um projeto totalmente funcional que você possa compilar. Isso deve soar como algo não tão importante para você, mas é uma coisa enorme para aplicações comerciais. Nós apenas queremos nos livrar do fato de que o aplicativo .NET é um livro aberto que qualquer pessoa com conhecimento absolutamente zero pode ler. Quando investimos milhares de dólares em pesquisa, não queremos que todos vejam e copiem em alguns segundos. Queremos nos livrar de pagar milhares de dólares por um ofuscador cujo único propósito é renomear todos os nomes de variáveis ​​e métodos, para que as pessoas não possam mais abrir o aplicativo e procurar por "licença" para acessá-lo imediatamente. Não são apenas (mas principalmente) os custos do ofuscador, mas também que os ofuscadores criam problemas adicionais. Eu me deparei com isso com bastante frequência, especialmente com a frequência dos lançamentos do .NET Core. Tivemos que esperar várias semanas apenas por um patch que fizesse o ofuscador funcionar com a versão mais recente do .NET Core.

E enquanto você enfrenta todos esses problemas como desenvolvedor, você também precisa explicá-los ao seu gerente de negócios. Em algum momento, ele pode perguntar se não é melhor escolher uma linguagem de programação diferente.

Com C++ e Delphi você simplesmente não tem esse problema. Eu sei que isso não é um problema para todos. Desenvolvedores de código aberto acharão o JIT mais interessante e útil. É difícil explicar a eles por que alguém quer que seu código-fonte seja um livro fechado, quando eles acreditam que livros abertos são apenas melhores. Então, idealmente, não precisamos explicar um ao outro nossas visões completamente diferentes e o AOT será apenas um interruptor que você pode ativar no modo de lançamento, se quiser. E se você não quiser, vá em frente com o JIT.

Estou muito agradecido pela equipe .NET nos deixar escolher "proteção" como uma razão pela qual queremos AOT ❤. Isso mostra que eles estão cientes das necessidades que algumas pessoas têm. E se as pesquisas revelarem que o homem vota nele, podemos finalmente ter uma chance de que a implementação AOT cuide disso da mesma maneira que um compilador C++. FYI: Eu coloquei entre aspas para evitar mais discussões sobre quanta proteção o AOT realmente é, os pontos de vista são extremamente amplos neste, como já devemos ter notado.

Segurança não é tudo ou nada. A remoção de IL não impede que um determinado invasor reverta um aplicativo. Mas cria obstáculos que são relevantes em um sentido prático. É defesa em profundidade. É por isso que os produtos de ofuscação IL podem ser de uso racional.

Um amigo meu quebrou produtos .NET descompilando IL para C# e fazendo modificações bastante triviais. Ele não é capaz de quebrar aplicativos nativos. É muito mais difícil. Ele também teve que desistir na presença de ofuscadores de IL porque a ferramenta descompiladora travou nesses binários. Mais uma vez, esses produtos foram protegidos em um sentido prático. Funcionou.

@Symbai

Have you ever seen a tool like dnSpy for C++ code? Delphi code?

Hex-Rays faz um bom trabalho para C, e tem macros para ajudar no processo de decisão.

Tendo fonte C é uma brincadeira de crianças para convertê-lo em C++ ou Delphi.

Além disso, agora temos IA para ajudar aqueles que não são habilidosos o suficiente.

Engenharia Reversa Neural de Binários Despojados

Hex-Rays faz um bom trabalho para C, e tem macros para ajudar no processo de decisão.

Você trabalha para a Hex-Rays ou para uma empresa que vende software de ofuscação? Parece que.

De qualquer forma, mesmo se você convertê-lo para C, o código estará muito longe de uma boa arquitetura C#. Mesmo se você conseguir pedaços do código, você terá que se esforçar bastante para mudar, melhorar, etc...
Se para você a compilação nativa for irrelevante, ok. Mas para muitas pessoas é relevante.

BTW: Você parece muito interessado em manter a compilação JIT e também parece ter muita experiência em desmontagem de software. Eu estou querendo saber por que e onde você teve que usar isso?!

Independentemente de como qualquer um de vocês se sinta sobre a facilidade de descompilação de IL versus código de máquina, isso não muda o fato de que é um requisito real em empresas reais. (E poderíamos discutir sobre o quão válido ou inválido esse requisito pode ser até que as vacas voltem para casa.)

Meu empregador anterior proibia explicitamente o envio de ferramentas .NET ou JVM externamente por esse motivo. Logo antes de eu sair, uma equipe convenceu os superiores a deixá-los enviar uma ferramenta com forte ofuscação aplicada, mas, fora isso, estávamos escrevendo ferramentas externas em C++ para satisfazer a política corporativa.

Essa discussão saiu dos trilhos. Se todos vocês querem discutir se o AOT é relevante para a proteção de IP, por favor, façam isso em outro lugar.

Hex-Rays faz um bom trabalho para C, e tem macros para ajudar no processo de decisão.

Você trabalha para a Hex-Rays ou para uma empresa que vende software de ofuscação? Parece que.

De qualquer forma, mesmo se você convertê-lo para C, o código estará muito longe de uma boa arquitetura C#. Mesmo se você conseguir pedaços do código, você terá que se esforçar bastante para mudar, melhorar, etc...
Se para você a compilação nativa for irrelevante, ok. Mas para muitas pessoas é relevante.

BTW: Você parece muito interessado em manter a compilação JIT e também parece ter muita experiência em desmontagem de software. Eu estou querendo saber por que e onde você teve que usar isso?!

Pelo contrário, possuo as habilidades para fazer engenharia reversa de código nativo para código-fonte que pode ser usado por terceiros, então estou plenamente ciente de que compilar para código nativo é apenas um obstáculo para script kiddies, o que parece ser o entendimento que faltava aqui.

EDIT: Também parando meus comentários. Só queria responder ao ataque pessoal.

Cloud Native e WPF devem ser AOT.
Cliente Windows sem tempo de execução! sem JIT

Os resultados da pesquisa foram publicados - https://github.com/dotnet/runtime/issues/41522. Estamos agora no processo de acompanhamento das pessoas que forneceram suas informações de contato e têm algumas perguntas adicionais de acompanhamento.

AOT com link estático é urgentemente necessário para mecanismos de jogos no iOS e plataforma de console que desativam o jit,

Concordo totalmente aqui. Como precisamos de uma solução para esse problema (código C# rodando em consoles de jogos para um projeto não Unity), estamos usando uma cadeia de ferramentas baseada em Mono-AOT. Mas tem algumas limitações sérias e não funciona tão bem.

Portanto, estamos tentando fazer o CoreRT rodar em 3 consoles de álamo (XBox One; PlayStation 4 e Nintendo Switch). Um teste inicial de conceito mostra que ele realmente funciona (ainda com algumas limitações), mas já com uma melhoria significativa no desempenho do tempo de execução em comparação com a solução baseada em Mono.

Mas com a situação do NDA em torno dos consoles de jogos, o suporte oficial para essa causa de uso é ainda mais improvável do que obter o AOT nativo oficial em primeiro lugar.

@RalfKornmannEnvision Você está usando as portas Xamarin Xbox One/PS4 Mono com codegen LLVM?

@RalfKornmannEnvision Você está usando as portas Xamarin Xbox One/PS4 Mono com codegen LLVM?

@lateralusX Como a integração foi feita por outra pessoa não sei nenhum detalhe. Mas até onde eu sei eles usaram as portas mono que são fornecidas para o XBox One/PS4 e fizeram uma porta simples para o Switch. eles mesmos.

@RalfKornmannEnvision Seria ótimo entrar em contato e discutir a experiência relacionada a isso. O codegen LLVM tem (dependendo do projeto) efeitos de desempenho muito positivos no código gerado, portanto, se isso não foi usado (precisa ser ativado), normalmente há muito a ganhar apenas ativando isso. Você está no servidor de discórdia DotNetEvolution, se sim, talvez possamos ter uma discussão offline relacionada a isso?

@lateralusX Tenho certeza de que os membros da equipe que trabalharam nisso habilitaram o codegen LLVM e tentaram outras coisas. Sua última declaração antes de passar para outro projeto foi que este é o melhor que eles poderiam fazer.

Como parte da minha investigação, construo um benchmark com o componente principal usando o Xamarin Android e o executo em um dispositivo baseado em Tegra X1 para ver se perdemos desempenho devido a um problema com nossa porta Switch personalizada do Mono. Infelizmente, o desempenho do projeto Xamarin não foi tão diferente do que vimos no Switch.

Lamento não estar neste servidor de discórdia e, para ser honesto, não sei muito sobre a integração MONO atual. Do meu ponto de vista, é um beco sem saída para este projeto. O atual protótipo CoreRT (embora tenha ainda menos suporte oficial) já é muito superior quando se trata de desempenho e usabilidade.

@RalfKornmannEnvision OK, obrigado por suas informações e comentários, todos muito valiosos.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

iCodeWebApps picture iCodeWebApps  ·  3Comentários

jzabroski picture jzabroski  ·  3Comentários

aggieben picture aggieben  ·  3Comentários

nalywa picture nalywa  ·  3Comentários

GitAntoinee picture GitAntoinee  ·  3Comentários