Pergunta

Estou fazendo algumas experiências com o Microsoft Dynamics CRM. Você interagir com ele através de serviços web e eu adicionei uma referência da web ao meu projeto. A interface de serviço web é muito rica, e os gerados "Reference.cs" é algum 90k loc.

Eu estou usando a referência da web em um aplicativo de console. Costumo mudar alguma coisa, recompilação e correr. Compilação é rápido, mas Newing-se a referência de serviço web é muito lento, levando cerca de 15-20 segundos: CrmService service = new CrmService(); Profiling revela que todo o tempo é gasto no construtor SoapHttpClientProtocol.

O culpado é, aparentemente, o fato de que o código de serialização XML (não incluído no loc 90k mencionado acima) é gerado em tempo de execução, antes de ser JIT'ed. Isso acontece durante a chamada do construtor. A espera é um pouco frustrante quando se joga ao redor e tentar coisas fora.

Eu tentei várias combinações de sgen.exe, ngen e XGenPlus (que leva várias horas e gera 500 MB de código adicional), mas sem sucesso. Eu considerei a implementação de um serviço do Windows que têm poucos casos CrmService pronto para repartir quando necessário, mas que parece excessiva.

Todas as idéias?

Foi útil?

Solução

O seguinte é rasgado de esta discussão nos fóruns VMWare:

Oi pessoal,

Descobrimos que sgen.exe funciona. It'just que há um par de passos adicionais para além de pré-gerar a dll serializador é que perdemos neste segmento. Aqui é a instrução detalhada

PROBLEMA

Ao usar o SDK VIM 2.0 do .NET requer muito tempo para instanciar a classe VimService. (A classe VimService é a classe proxy gerado executando 'wsdl.exe vim.wsdl vimService.wsdl')

Em outras palavras, a seguinte linha de código:

_service = new VimService();

Pode demorar cerca de 50 segundos para executar.

Causa

Aparentemente, o XmlSerializer .NET usa o System.Xml.Serialization.* atributos anotar as classes de proxy para gerar código de serialização em tempo de execução. Quando as classes de proxy são muitas e grandes, como é o código na VimService.cs, a geração do código de serialização pode levar um longo tempo.

SOLUÇÃO

Este é um problema conhecido com como funciona o serializador Microsoft .NET.

Aqui estão algumas referências que MSDN fornece sobre como resolver esse problema:

http://msdn2.microsoft.com/en-us/library/ bk3w6240.aspx http://msdn2.microsoft.com/en-us /library/system.xml.serialization.xmlserializerassemblyattribute.aspx

Infelizmente, nenhuma das referências acima descrevem a solução completa para o problema. Em vez disso, se concentrar em como pré-gerar o código de serialização XML.

A correção completa envolve as seguintes etapas:

  1. Criar um conjunto (uma DLL) com o código serializador XML pré-gerado

  2. Remova todas as referências a System.Xml.Serialization. * Atributos do código de proxy (ou seja, a partir do arquivo VimService.cs)

  3. Anotar a principal classe de proxy com o XmlSerializerAssemblyAttribute para apontar para onde o serializador XML é montagem.

Skipping passo 2 leva à melhoria de apenas 20% no tempo de instanciação para a classe VimService. Ignorando qualquer passo 1 ou 3 conduz ao código incorrecto. Com todos os três passos% de melhoria 98 é alcançado.

Aqui estão as instruções passo-a-passo:

Antes de começar, certifica-se de que você está usando .NET verison ferramentas 2.0. Esta solução não funcionará com a versão 1.1 do .NET porque a ferramenta SGen eo XmlSerializationAssemblyAttribute só estão disponíveis na versão 2.0 do .NET

  1. Gerar o arquivo VimService.cs do WSDL, utilizando wsdl.exe:

    wsdl.exe vim.wsdl vimService.wsdl

    Esta vontade de saída do arquivo VimService.cs no diretório atual

  2. Compilar VimService.cs em uma biblioteca

    csc /t:library /out:VimService.dll VimService.cs

  3. Use a ferramenta SGen de pré-gerar e compilar os serializers XML:

    sgen /p VimService.dll

    A saída será o VimService.XmlSerializers.dll no diretório atual

  4. Volte para o arquivo VimService.cs e remover todos os atributos System.Xml.Serialization.*. Como o código de código é grande, a melhor maneira de conseguir isso é usando alguma ferramenta regular de substituição expressão. Tenha cuidado como você faz isso porque nem todos os atributos aparecem em uma linha por si mesmos. Alguns são in-alinhados como parte de uma declaração de método.

    Se você encontrar esta etapa difícil, aqui é uma maneira simplificada de fazê-lo:

    Assumindo que você está escrevendo C #, não uma substituição global na seguinte seqüência:

    [System.Xml.Serialization.XmlIncludeAttribute

    e substituí-lo:

    // [System.Xml.Serialization.XmlIncludeAttribute

    Isso vai se livrar dos atributos Xml.Serialization que são os maiores culpados para a desaceleração comentando-los. Se você estiver usando alguma outra linguagem .NET, basta modificar the substituído string para ser de acordo com a sintaxe dessa língua comentou-prefix. Esta abordagem simplificada, poderá ir a maior parte do aumento de velocidade que você pode obter. Removendo o resto do Xml.Serialization atributos só atinge um adicional aumento de velocidade de 0,2 s.

  5. Adicione o seguinte atributo à classe VimService em VimService.cs:

    [System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")]

    Você deve acabar com algo parecido com isto:

    // ... Some code here ... [System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")] public partial class VimService : System.Web.Services.Protocols.SoapHttpClientProtocol { // ... More code here

  6. Regenerar VimSerice.dll biblioteca por

    csc /t:library /out:VimService.dll VimService.cs

  7. Agora, a partir de sua aplicação, você pode adicionar uma referência à biblioteca VimSerice.dll.

  8. Execute o aplicativo e verificar que o tempo VimService objeto instanciação é reduzida.

NOTAS ADICIONAIS

A ferramenta SGen é um pouco de uma caixa preta e seu comportamento varia de acordo com o que você tem no seu arquivo Machine.config. Por exemplo, por padrão, ele é suposto ouptut código não-debug otimizado, mas que nem sempre é o caso. Para obter alguma visibilidade sobre a ferramenta, use o sinalizador / k no passo 3, o que fará com que ele para manter todos os seus arquivos gerados temporários, incluindo os arquivos de origem e arquivos de opções de linha de comando que gerou.

Mesmo após a correção acima o tempo que leva para instanciar a classe VimService pela primeira vez não é instantânea (1,5 seg). Com base na observação empírica, parece que a maioria do tempo restante é devido ao processamento dos atributos SoapDocumentMethodAttribute. Neste ponto, não está claro como esse tempo pode ser reduzido. O XmlSerializer pré-gerado montagem não leva em conta os atributos relacionados em SOAP, então esses atributos precisam permanecer no código. A boa notícia é que apenas a primeira instanciação da classe VimService para esse aplicativo leva muito tempo. Então, se o extra 1,5 segundos são um problema, pode-se tentar fazer uma instanciação manequim desta classe no início da aplicação como um meio para melhorar a experiência do usuário de tempo de login.

Outras dicas

Você pode querer olhar para o Sgen.exe ferramenta que vem com .NET. Há também uma pequena coisa útil em C # propriedades de projecto do estúdio página Visual "Build", na parte inferior, chamada "Build serialização de montagem" que é executado automaticamente Sgen para você.

Eu acredito que este não é um problema SGEN. Eu olhei o código do construtor, e vejo que ele está fazendo um monte de reflexão (baseada no XmlIncludeAttribute na classe). Ele reflete sobre todos eles, e pode levar um tempo muito longo.

Há um XmlSerializer pré-gerado montagem que vem com CRM. Verifique se você tem SdkTypeProxy.XmlSerializers.dll e SdkProxy.XmlSerializers.dll no GAC.

Se você não fizer isso, então isso significa que quando você criar o CrmService, .net irá gerar o XmlSerializer montagem que pode levar algum tempo. Espero que isso ajude

me deparei com esta discussão ao tentar descobrir por que minhas ligações SoapHttpClientProtocol iniciais foram demorando tanto.

Descobri que definir o Proxy como nulo / vazio parou o AutoDetect Proxy ocorra - Este foi tendo até 7 segundos na chamada inicial:

this.Proxy = GlobalProxySelection.GetEmptyWebProxy();

Eu usei acima resposta detalhada como guia, e foi alguns passos à frente, fazendo um script para automatizar processo. Script é feito de dois arquivos:

generateproxy.bat:

REM if your path for wsdl, csc or sgen is missing, please add it here (it varies from machine to machine)
set PATH=%PATH%;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools;C:\Program Files (x86)\MSBuild\14.0\Bin

wsdl http://localhost:57237/VIM_WS.asmx?wsdl REM create source code out of WSDL
PowerShell.exe -ExecutionPolicy Bypass -Command "& '%~dpn0.ps1'" REM proces source code (remove annotations, add other annotation, put class into namespace)
csc /t:library /out:references\VIM_Service.dll VIM_WS.cs REM compile source into dll
sgen /p references\VIM_Service.dll /force REM generate serializtion dll

generateproxy.ps1

(Get-Content VIM.cs) | 
    ForEach-Object { 
        $_ -replace "(?<attr>\[global::System.Xml.Serialization.[^\]]*\])", "/*${attr}*/" `
            -replace "public partial class VIM", "[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = ""VIM_Service.XmlSerializers"")] `npublic partial class VIM" `
            -replace "using System;", "namespace Classes.WS_VIM {   `n`nusing System;"
    } |
Set-Content VIM.cs
Add-Content VIM.cs "`n}"

Eu adicionei esses dois arquivos para projeto do cliente, e em caso de pré-build eu adicionei linhas

cd..\..
generateproxy

Assim, antes de cada compilação, classes de proxy são regenerados e desenvolvedor tem (quase) não há necessidade de pensar sobre isso. Enquanto edifício, WS deve ser instalado e funcionando, e sua URL deve estar no arquivo bat. Como resultado da prebuild, dois arquivos DLL irá regenerar em subpasta de projeto do cliente referências . Após a primeira execução de scripts, você deve adicionar referência a nova DLL.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top