I'm finding that when I first start up my application the first client dataportal usage PER TYPE, is very slow.
So, for example, the first Fetch of MyObject takes around 800ms, whereas every subsequent MyObject takes around 250ms (the server is in a different location). If I then Fetch MyOtherObject (without restarting the application), this first usage is slow, but subsequent usages are fine.
The server is running at all times using a SelfHosted server (not IIS) so should be fully up and running and with no startup delays, so I don't believe that the server-side is affecting things.
I've had a look around at the usual suspects for first WCF usage being slow, but neither seems to make a difference:
- proxy detection (I don't have a proxy and have tried setting the relevant config file things to disable)
- serialization (I have tried forcing serialization of MyObject manually before first using the DataPortal)
I am not specifying a serializer, so I think this means that it will be using BinaryFormatter. I have my DataPortal configured to use NetTcp with transport level security.
The thing is, if this was slow for the first usage for ALL objects (i.e. the first usage of the first type is slow, but aftewards everything is fine), I would assume this is a WCF thing, but because the first usage of every type is slow, it makes me think this has something to do with CSLA and the way it does things.
This is also the same in a Release build after ngen-ing the binaries.
Does anyone have any other ideas for what could be causing this? Does anyone else see the same issue?
Could it be to do with the fact that the WCF service is based upon reflection (dynamic typing) and how the serialization handles this?
How about the initialization of rules.
AddObjectAuthorizationRules and AddBusinessRules methods is called only the first time you touch an object of that type. Do you do any database access or other possible time consuming operations in one of these methods?
It could also be caused by initialization of KeyValuePair lists used by rules when they fetch the initial list from the database (and cache them internally so you do not get the cost on next access).
Thanks for the reply Jonny.
I've checked and we are using per-type Auth and Business rules, but none of these fetch data from the DB.
The BusinessRules are all using CSLA simple rules such as MaxLength etc. with hardcoded values.
The Auth Rules use some AuthorizationRule derived classes, but their data is all pre-loaded into a client cache on app startup (and besides the call to access this data is within Execute on the rule only).
I have put traces into the client DataPortalInvoke and DataPortalInvokeComplete as well as some tracing on the server-side in the DataPortal_OnDataPortalInvoke and DataPortal_OnDataPortalInvokeComplete. It appears that the major delay comes between the DataPortal_OnDataPortalInvokeComplete on the server and the DataPortalInvokeComplete on the client side.
Any ideas what could be causing this?
Side note: These are Sync requests, not Async.
I would suggest that you run a Profiler - Performance Session to determine where the CPU time is consumed.
This is exactly what I did yesterday.
There are two places that are significantly slower the first usage than the second:
Both are during the client read (Csla.DataPortalClient.WcfProxy+<Fetch>d__a.MoveNext())
I have tested on other networks so don't think it is a transmission issue. It looks like it is the NDCS being slow deserializing.
I've checked and CSLA is definitely using the BinaryFormatter, so I guess the NDCS seems to be slow deserializing the WcfResponse object?
I am going to have a play with pre-serializing some of the objects to see if this speeds things up.
I've switched to basicHttpBinding to rule out any net.tcp weirdness, but am still getting the same delay.
One thing I have noticed is that now I can view the raw http data in Fiddler, the Object data appears to be Xml encoded.
However, when I put a breakpoint on my csla Server, the ApplicationContext.SerializationFormatter is set to BinaryFormatter.
I was expecting therefore in the raw Http request/response in Fiddler to see Xml versions of the CSLA Request/Criteria/WcfResponse classes, but with raw binary data for the object data field. Should I?
I wonder if something is misconfigured to cause the BinaryFormatter not to be used?
Following on from my previous reply, could someone clarify something around the serialization. The "Using CSLA 4 - Data Portal" e-book says:
"The WCF data portal channel uses the NDCS, because that is how
WCF serializes data for transfer over the network. Even when the WCF data portal channel is used,
CSLA .NET defaults to using the BinaryFormatter for all serialization operations outside the data
Does this mean that when WCF is used as the transport NDCS is used for serialization of the objects no matter what CSLA is configured to use?
Data is serialized in 2 steps:
This is strange...because I don't think I am seeing this.
When I set the basicHttpBinding for the WCF service and ran Fiddler over the communications, I could see the objects were serialized in XML - I could read all of the property names and values etc.
I was expecting, and judging by your reply what I should see, to see an Xml response object within which is a property which contains a blob of raw data of the object.
At runtime, CSLA is definitely stating that the ApplicationContext.SerializationFormatter is BinaryFormatter though.
There are a number of data portal channel implementations, so it depends on which you are using (and which version of CSLA).
The _mobile_ WcfProxy does this:
The _non-mobile_ WcfProxy does this:
The HttpProxy does this:
I guess that explains why I am seeing XML serialization as we are using the non-mobile WcfProxy.
I've managed to speed up first usage by forcing types through the NCDS at startup, but it's not ideal. I guess I can't use the svcutil to generate the XmlSerialisers.dll because the WcfProxy DataContract properties are "object" and don't know about my types!
Jonny is right though, if you haven't run a profiler you could be wasting your time on the serialization issue.
Agreed - and this is what I first did. See earlier reply
There are two places that are significantly slower the first usage than the second: System.Net.Socket.Receive - and System.Runtime.Serialization.ClassDataContract.ReadXmlValue Both are during the client read (Csla.DataPortalClient.WcfProxy+<Fetch>d__a.MoveNext())
I've now got something running on app startup to find all serializable types in my assemblies and to run them through the NetDataContractSerializer. The speed of the first usage of the DataPortal for each type in the same ball park as subsequent uses.
But it does take about 30-45 seconds to run through all of my types at startup, so its not ideal. I know that first usage of Xml Serialization is known to be slow, and you can pre-generate the serialization data for them (see http://msdn.microsoft.com/en-us/library/aa751883.aspx) but unfortunately because the CSLA DataContract is simply "object", if I run the svcutil over it, it isn't going to know about my types at that point!
Is there any way to get the non-mobile proxy to use the same mechanism as the mobile one re: binary formatting the objects first before adding to the request/response? I am using binaryMessageEncoding (and net.tcp) in WCF, but I feel I am losing the benefit when the entire objects are first being serialized into XML by the NCDS.
If you are using CSLA 4 I'd recommend just switching to the "mobile" data portal. In version 4.5 I think the mobile implementation is generally better than the previous implementation, and works universally across all the supported platforms (well, to be fair, HttpProxy works _everywhere_, but the mobile WcfProxy works most places).
I'd like to try it, but at first attempt I have serialization errors (I fixed the first one around Generic Principal, but swiftly moved on to another) "Serialization of type object is not supported."
The application I have inherited has approximately 1300 objects based up CSLA base classes (which I suppose *should* just work as the bases implement IMobileObject). There are also ton of other criteria objects that are just POCOs though, so I would need to convert these to CriteriaBase. I feel I might be pulling at a thread with this...!
I take it that I can't use the Mobile DataPortal with BinaryFormatter!?
You could write your own data portal channel :)
Seriously though, you really could. Look at the HttpProxy and host implementation for instance. In this case the proxy and host code directly serialize/deserialize the data, and the network is simply passing a binary byte array over the wire.
You could use a very similar implementation but use WCF as the network transport instead of a direct HTTP call.
Copyright (c) Marimer LLC