3

I wanted to create a WCF service that would separate the Tridion Content Delivery functionality so that I wouldn't add Tridion References to my Web App. Instead of referencing Tridion.ContentDelivery.dll directly in a Web App solution I would make service calls in the data layer(This is because I need a single source of Tridion content for multiple applications). Both Web App and the WCF Service use Unity for Dependency Injection. The WCF is IIS hosted. Both are .NET 4.5

An example method that fetches the data:

public List<ContentComponent> GetRelatedContent(RelatedContentRequest request)
{
    string[] results = null;
    ItemTypeCriteria typeCriteria = null;
    PublicationCriteria publicationCriteria = null;
    ItemSchemaCriteria schemaCriteria = null;
    TaxonomyKeywordCriteria taxonomyKeywordCriteria = null;
    Query query = null;
    ComponentPresentation presentation = null;
    List<Criteria> criterias = null;
    List<ComponentPresentation> componentPresentations = null;
    try
    {
        query = new Query();
        criterias = new List<Criteria>();
        componentPresentations = new List<ComponentPresentation>();
        publicationCriteria = new PublicationCriteria(request.PublicationId);
        criterias.Add(publicationCriteria);
        typeCriteria = new ItemTypeCriteria(COMPONENT_TYPE);
        criterias.Add(typeCriteria);
        if (request.SchemaId > 0)
        {
            schemaCriteria = new ItemSchemaCriteria(request.SchemaId);
            criterias.Add(schemaCriteria);
        }
        taxonomyKeywordCriteria = new TaxonomyKeywordCriteria(request.TaxonomyUri, request.KeywordUri, request.IncludeChildKeywords);
        criterias.Add(taxonomyKeywordCriteria);
        query.Criteria = CriteriaFactory.And(criterias.ToArray());
        results = query.ExecuteQuery();
        foreach (string compURI in results)
        {
            using (ComponentPresentationFactory factory = new ComponentPresentationFactory(compURI))
            {
                presentation = factory.GetComponentPresentation(compURI, request.DynamicTemplateUri);
            }
            if (presentation != null && !string.IsNullOrEmpty(presentation.Content))
            {
                componentPresentations.Add(presentation);
            }
        }
    }
    catch (System.Exception)
    {
    }
    finally
    {
        if (publicationCriteria != null) publicationCriteria.Dispose();
        if (schemaCriteria != null) schemaCriteria.Dispose();
        if (taxonomyKeywordCriteria != null) taxonomyKeywordCriteria.Dispose();
        if (typeCriteria != null) typeCriteria.Dispose();
        if (query != null) query.Dispose();
        if (criterias != null) criterias.Dispose();
    }
    if (componentPresentations != null)
    {
        List<ContentComponent> result = componentPresentations.ConvertAll(c => new ContentComponent() { ComponentId = c.ComponentId, Content = c.Content });
        componentPresentations.Dispose();
        return result;
    }
    return null;
}

ContentComponent and RelatedContentRequest are my custom classes. The data is returned correctly and the service works fine when I develop but when doing some load testing I run into issues. There is a memory leak. After making about 100 requests the WCF process memory grows to about 2GB. If I use http binding for the service it reaches a plateau of about 2GB but continues to respond. If I use net.pipe or net.tcp the service becomes non responsive after about 50 requests. Inspecting with dotMemory I see a lot of memory being used by unmanaged code.

I've tried using Tridion OData service instead of Tridion Delivery Content dlls but I cannot implement every functionality required using only OData.

Am I doing something wrong? Am I not disposing the items correctly?

3

In order to troubleshoot a Memory Leak you should first create a Dump file for the WCF related process. When you say WCF process I assume you refer to WAS.

The memory Dump will let you know which kind of objects are not properly released from memory and also it will tell you how efficient are the execution threads.

Once you determine which objects are causing the Memory Leak, you can determine which part of your code is causing it. For instance if you notice that Java Objects are the ones not being released then it more likely related to Tridion Objects. However, it can be related to the WCF serialization process (Text vs Binary)

I would recommend to don't use WCF for such kind of interfaces, I would say ASP .NET Web API is more suitable for this kind of interfaces.

I hope this helps.

  • We've uses WCFs to drive DD4T sites inthe same way and not had thia kind of memory issue. You can use DebugDiag to tale your memory dumps. – Neil Sep 20 '14 at 11:14
  • Neil, W tried doing the same - we added DD4T functionality to our service but got really strange behaviour - hundreds of db calls all of them obsolete and all happening after the request has been fulfilled, inside netrtsn.dll – pete Sep 22 '14 at 10:17
  • Eric but what if we want to leverage net.tcp and net.pipe bindings? We cannot do that with Web API. I'll look at the Dump. – pete Sep 22 '14 at 10:20
  • No you cannot, Web API is intended for the Web, WCF tcp and net pipes are intended for internal services, for instance internal application within your intranet – Eric Huiza Sep 22 '14 at 12:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.