I've read that assembly serialization (sgen.exe) can improve performance.
What exactly is providing the improvement?
Is it metadata on the Types? I would have thought this would be available through reflection! so why is it required in a separate assembly?
The serialization assemblies Data.XmlSerializers.dll which improve the performance of clients that use XML Web service proxies to communicate with servers is described under http://msdn.microsoft.com/en-us/library/bk3w6240.aspx.
If you don't do this the same work will be done at the first usage of XmlSerializer. In the blog Link is described additional setting in <system.diagnostics> area of the application.config file to see more what do XmlSerializer in the background.
In Visual Studio there are a spetion setting in the "Build" tab of project settings (see http://www.eggheadcafe.com/tutorials/aspnet/8eb0e68f-5496-4363-9cb9-dd68447ba187/xml-serializer-generator.aspx). So you not really need to use sgen.exe manually.
To more understand what sgen.exe do you can load an open source version of sgen.exe: xgenplus http://xgenplus.codeplex.com/.
I recommend you aslo to read SGEN XMLSerializer - should be .XMLSerializers.dll added as a reference to the current project or to the GAC?.
If you search in google for XmlSerializer and sgen you will find all the information and even more on the first page of the serch results.
Related
I have some older projects in non-SDK style which were created using Visual Studio; the csproj files were almost never modified manually. They were done partly by colleages before I came to this company, so I have very incomplete knowledge about what should or shouldn't be in these files.
Now I am trying to turn them into SDK-style projects by manually modifying the csproj files. In order to do that, I need to understand for each tag what it is for, and if it can be omitted or must be modified.
There might be
non-SDK-style leftovers that can just be deleted,
content we were not aware of (because we don't always know what we are doing when playing around with settings in a project),
content that needs to be modified to fit the new SDK-style specification,
content that can be omitted because it contains just its default value,
etc.
I try getting by by googling a given tag together with "csproj", but more often than not I cannot find useful content. I also noticed that most of the time I DO NOT find a source from Microsoft, mostly blog entries by private guys that sometimes, sometimes not tell me what I want to know.
There are some Microsoft docs like sdk reference or common properties, but they do not cover all tags that I have in my project.
So, how can I understand the content of my csproj file? Is the documentation there and I am merely not finding it? If so, what to search for? Shouldn't Microsoft have a comprehensive list of all possible tags? They have invented the csproj format, so they should know. Or do I need to learn something else first that is a prerequisite of working with csproj files (like before constructing bridges one should know about basic algebra and calculus), that will help me figure out stuff on my own?
cproj files can have a lot of project configurations. Visual Studio Extensions might also modify cproj files and add custom values.
As per the comments on this answer, there isn't a complete list of available properties for Visual Studio projects. The links provided in the question contains most used properties, so that should cater for the average project.
It is very rare that properties will be used that is not contained in those links. If you do run across an unknown property, try searching online, if that fails, ask on SO.
A good search query that hasn't failed me yet, {Project Type} "{Property}" csproj property : .Net "TestProjectType" csproj property.
I use a production library (namely itextsharp) in my project, this library doesn't ship with intellisense documentation.
I'd like to build (partial) documentation project.
Is this possible without access to the source code?
I think that intellisense data for external libraries are defined in a xml file which should ship alongside the said library. It should also have the same named but an xml extension instead of dll.
There are a bunch of xml tags that Intellisense will expect which are documented on msdn. Also some open source libraries come with such documentation, like Unity for instance, which will give you a "working" example of such a xml file. You can find an example here on github
I’m trying to create add-in for outlook and have issue with deserialization and antivirus program.
I’ve noticed that when my add-in tried to deserialize any data, .NET framework created temporary dll in “C:\Users\{UserName}\AppData\Local\Temp\" folder.
This dll existed very short time, but from time to time antivirus locked it and add-in thrown error message that file is used by another process.
I’m tried to get rid of temporary dll and found recommendations to use sgen tool for creation of XmlSerializers.dll.
I generated MyAssembly. XmlSerializers.dll with strong name and placed it to the folder with add-in (C:\Program Files (x86)\MyAddin). But it doesn’t help.
Then I tried to place MyAssembly. XmlSerializers.dll to GAC and then to outlook folder, but had no success. When dll was called from GAC I got following error message, but dll has no any reference.
"System.IO.FileNotFoundException: Could not load file or assembly or
one of its dependencies. The system cannot find the file specified."
Please add any thoughts how can I to get rid of temporary dll
When an XmlSerializer for a type is first constructed, internally the XML serialization engine generates c# code to serialize and deserialize the type, writes it to %TEMP% in temporary file(s), then compiles and loads the resulting assembly, finally deleting any temporary files. (Subsequent usages of XmlSerializer reuse the created assembly, see here for details.)
It looks as though your antivirus software is being ultra-aggressive at scanning any "unexpected" files created by the Outlook process, immediately trapping the creation of the file and scanning the results. While under most circumstances this would seem praiseworthy, it clearly conflicts with Microsoft's design for XmlSerializer.
So, what to do about this? You have several options:
Switch to DataContractSerializer, which does not use this architecture. DataContractSerializer is less flexible that XmlSerializer, however, and may not be able to parse your XML without preprocessing it.
Enable precompiled serialization assemblies. It's not sufficient to simply set GenerateSerializationAssemblies = On as is specified in the documentation, you have to jump through several hoops to make this actually work. See answers to Generating an Xml Serialization assembly as part of my build for ways to do it. I was able to make the accepted answer work with my old Visual Studio 2008 by editing my project file as described and then removing the Platform="$(Platform)" attribute. You might need to tweak the answer differently for your VS version.
After actually enabling pre-generated serialization DLLs I verified with Process Monitor that no files were written to %TEMP% when deserializing XML in a test console application.
See also here: Boost performance with Pre-generated XmlSerializers.
Update
After a bit of testing, I found that, if your root object does not exist in the assembly you are building, or if is a generic collection like List<T> or T [], then precompiled serializer assemblies are not used. However, making a non-generic subclass of List<T> re-enables serializer assemblies, e.g. public class RootObjectList : List<RootObject> { }.
For more, see here: All about XmlSerializer Performance and Sgen.
Convert your XML to JSON with Json.NET, then deserialize the JSON.
If your XML is simple, you could load it into an XDocument and query it with Linq to XML.
I do some stuff with XMLSerializer class. Like a most of beginners I face with performance issue on app start. I read a lot of blogs, articles and finally use SGEN tool. Now performance looks to be ok but few things are still not clear for me.
1) Should I use SGEN syntax like this:
SGen.exe /assembly:MyAssembly /type:MyRootXmlType
or it's enough to just (I use this syntax currently, I have only one Serializable class in my assembly):
SGen.exe /assembly:MyAssembly
When /type parameter can be useful in practice?
2) I read on MSDN ( http://msdn.microsoft.com/en-us/library/ee704594.aspx )
This command generates the serializer
assembly
MyAssembly.XmlSerializers.dll, which
should be added as a reference to the
current project or to the GAC.
but on all other blogs and articles (for example on SO) I read that is enough to just put MyAssembly.XmlSerializers.dll into folder where MyAssembly exists.
So what is right?
3) It's enough to just generate .XmlSerilizers.dll and deploy it together with MyAssembly or should I add something to my code yet?
I don't think so but I would like to be sure that I will not have to change my code and "magic" happens automatically.
If you don't use the /type argument for sgen.exe then it will generate de/serialization code for all public types in the assembly. Note that the [Serializable] attribute is not used in XML serialization. I doubt you'd want this, use /type to keep the generated assembly small.
Adding a reference is not necessary, Xml serialization always tries an Assembly.Load() on the .XmlSerializers.dll assembly anyway. Plus, you'll never reference the generated XmlSerializationWriterXxx and XmlSerializationReaderXxx classes directly in your code. It does have one advantage, the build system will automatically copy the assembly when you include the project in a solution.
Installing it in the GAC is only worth considering when different apps serialize and deserialize the XML file. You can provide other apps with the .XmlSerializers.dll assembly by copying the assembly by hand as well. Which is a bit error prone, use your own judgment here. Check the previous paragraph for a way to automate the copy.
I'm doing some experiments with Microsoft Dynamics CRM. You interact with it through web services and I have added a Web Reference to my project. The web service interface is very rich, and the generated "Reference.cs" is some 90k loc.
I'm using the web reference in a console application. I often change something, recompile and run. Compilation is fast, but newing up the web service reference is very slow, taking some 15-20 seconds:
CrmService service = new CrmService();
Profiling reveals that all time is spent in the SoapHttpClientProtocol constructor.
The culprit is apparently the fact that the XML serialization code (not included in the 90k loc mentioned above) is generated at run time, before being JIT'ed. This happens during the constructor call. The wait is rather frustrating when playing around and trying things out.
I've tried various combinations of sgen.exe, ngen and XGenPlus (which takes several hours and generates 500MB of additional code) but to no avail. I've considered implementing a Windows service that have few CrmService instances ready to dish out when needed but that seems excessive.
Any ideas?
The following is ripped from this thread on the VMWare forums:
Hi folks,
We've found that sgen.exe does work. It'just that there is a couple of additional steps beyond pre-generating the serializer dll's that we missed in this thread. Here is the detailed instruction
PROBLEM
When using the VIM 2.0 SDK from .NET requires long time to instantiate the VimService class. (The VimService class is the proxy class generated by running 'wsdl.exe vim.wsdl vimService.wsdl')
In other words, the following line of code:
_service = new VimService();
Could take about 50 seconds to execute.
CAUSE
Apparently, the .NET XmlSerializer uses the System.Xml.Serialization.* attributes annotating the proxy classes to generate serialization code in run time. When the proxy classes are many and large, as is the code in VimService.cs, the generation of the serialization code can take a long time.
SOLUTION
This is a known problem with how the Microsoft .NET serializer works.
Here are some references that MSDN provides about solving this problem:
http://msdn2.microsoft.com/en-us/library/bk3w6240.aspx
http://msdn2.microsoft.com/en-us/library/system.xml.serialization.xmlserializerassemblyattribute.aspx
Unfortunately, none of the above references describe the complete solution to the problem. Instead they focus on how to pre-generate the XML serialization code.
The complete fix involves the following steps:
Create an assembly (a DLL) with the pre-generated XML serializer code
Remove all references to System.Xml.Serialization.* attributes from the proxy code (i.e. from the VimService.cs file)
Annotate the main proxy class with the XmlSerializerAssemblyAttribute to point it to where the XML serializer assembly is.
Skipping step 2 leads to only 20% improvement in the instantiation time for the VimService class. Skipping either step 1 or 3 leads to incorrect code. With all three steps 98% improvement is achieved.
Here are step-by-step instructions:
Before you begin, makes sure you are using .NET verison 2.0 tools. This solution will not work with version 1.1 of .NET because the sgen tool and the XmlSerializationAssemblyAttribute are only available in version 2.0 of .NET
Generate the VimService.cs file from the WSDL, using wsdl.exe:
wsdl.exe vim.wsdl vimService.wsdl
This will output the VimService.cs file in the current directory
Compile VimService.cs into a library
csc /t:library /out:VimService.dll VimService.cs
Use the sgen tool to pre-generate and compile the XML serializers:
sgen /p VimService.dll
This will output the VimService.XmlSerializers.dll in the current directory
Go back to the VimService.cs file and remove all System.Xml.Serialization.* attributes. Because the code code is large, the best way to achieve that is by using some regular expression substitution tool. Be careful as you do this because not all attributes appear on a line by themselves. Some are in-lined as part of a method declaration.
If you find this step difficult, here is a simplified way of doing it:
Assuming you are writing C#, do a global replace on the following string:
[System.Xml.Serialization.XmlIncludeAttribute
and replace it with:
// [System.Xml.Serialization.XmlIncludeAttribute
This will get rid of the Xml.Serialization attributes that are the biggest culprits for the slowdown by commenting them out. If you are using some other .NET language, just modify the replaced string to be prefix-commented according to the syntax of that language. This simplified approach will get you most of the speedup that you can get. Removing the rest of the Xml.Serialization attributes only achieves an extra 0.2 sec speedup.
Add the following attribute to the VimService class in VimService.cs:
[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")]
You should end up with something like this:
// ... Some code here ...
[System.Xml.Serialization.XmlSerializerAssemblyAttribute(AssemblyName = "VimService.XmlSerializers")]
public partial class VimService : System.Web.Services.Protocols.SoapHttpClientProtocol {
// ... More code here
Regenerate VimSerice.dll library by
csc /t:library /out:VimService.dll VimService.cs
Now, from your application, you can add a reference to VimSerice.dll library.
Run your application and verify that VimService object instanciation time is reduced.
ADDITIONAL NOTES
The sgen tool is a bit of a black box and its behavior varies depending on what you have in your Machine.config file. For example, by default it is supposed to ouptut optimized non-debug code, but that is not always the case. To get some visibility into the tool, use the /k flag in step 3, which will cause it to keep all its temporary generated files, including the source files and command line option files it generated.
Even after the above fix the time it takes to instantiate the VimService class for the first time is not instantaneous (1.5 sec). Based on empirical observation, it appears that the majority of the remaining time is due to processing the SoapDocumentMethodAttribute attributes. At this point it is unclear how this time can be reduced. The pre-generated XmlSerializer assembly does not account for the SOAP-related attributes, so these attributes need to remain in the code. The good news is that only the first instantiation of the VimService class for that app takes long. So if the extra 1.5 seconds are a problem, one could try to do a dummy instantiation of this class at the beginning of the application as a means to improve user experience of login time.
You might wish to look into the Sgen.exe tool that comes with .NET. There's also a handy little thing in Visual Studio's C# project properties "Build" page, at the very bottom, called "Build serialization assembly" that automatically runs Sgen for you.
I believe that this is not an SGEN issue. I have looked at the constructor code, and I see that it is doing a lot of reflection (based on the XmlIncludeAttribute on the class). It reflects on all of them, and can take a really long time.
There is a pre-generated XmlSerializer assembly that comes with CRM. Check to see whether you have SdkTypeProxy.XmlSerializers.dll and SdkProxy.XmlSerializers.dll in the GAC.
If you don't then that means that when you create the CrmService, .net will generate the XmlSerializer assembly which can take some time.
Hope this helps
I came across this thread when trying to find out why my initial SoapHttpClientProtocol calls were taking so long.
I found that setting the Proxy to null/Empty stopped the Proxy AutoDetect from occurring - This was taking up to 7 seconds on the initial call:
this.Proxy = GlobalProxySelection.GetEmptyWebProxy();
I have used above detailed answer as guide, and went a few steps forward, making a script to automate process. Script is made out of two files :
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}"
I have added those two files to client project, and in the pre-build event I have added lines
cd..\..
generateproxy
So, before every build, proxy classes are regenerated, and developer has (almost) no need to think about it. While building, WS must be up and running, and its URL must be in bat file. As a result of prebuild, two dll files will regenerate in client project's subfolder references.
After first execution of scripts, you should add reference to new dll.