Help: how can I avoid the System.OutOfMemoryException?

Dear All,

A System.OutOfMemoryException always occurs in my program when the input data size becomes larger. Basically my program uses a recursive method to travel all paths in a graph. For example, the graph's configuration looks like this: three nodes A, B, and C. There is one edge between B and C, and the only thing that changes is the number of edges between A and B. When there are 2000 edges between A and B, my program works fine. But if I increase the number of edges to 3000 or more, the exception occurs.

I suspect most memory is consumed by this recursive method. Yet, memory should be released whenever such a method returns. Is it possible that the memory is not returned even if this method is logically correct And how can I solve the problem Any suggestions would be much appreciated!

SunnyDay



Answer this question

Help: how can I avoid the System.OutOfMemoryException?

  • jimcason

    Can you post your code (hopefully short and simplified) that reproduces the problem

    In particular, is the depth of recursion proportional to the problem size you stated, such as 2,000 or 3,000 An interative solution may be preferable to a recursive one for problems of such large size.

    -slj-


  • Heather Grantham

    Hi Scott,

    Thank you very much for your quick response!

    Ok, below is the method which traverses the graph. It computes the transitive relationships from a source class to a number of target classes, for a UML class diagram. For example, suppose there are three classes A, B, and C with two dependencies from A to B and one dependency from B to C. In this diagram, there are two directed paths from class A to C, and thus we can have two transitive relationships from A to C.

    Back to your question, the depth of recursion should NOT be proportional to the problem size. Since the only thing that is changed is the number of relationships between A and B, so the depth should always be 2. Now if the input size is 2000 (i.e., 2000 new edges are added from A to B), the program works fine. However, it fails when I increase it to 3000 or so.

    I am not quite sure if it is really this method that caused the problem since the program abnormally terminates at different points, showing error messages like exception in vjslib.dll, or mscorlib.dll ... But it is the only one I suspect that consumes large chunk of mem.

    Once again, your advice is appreciated.

    SunnyDay

    Input:
    fromClass: source node in the graph (e.g., class A)
    toClasses: a set of target nodes (e.g., class C)
    excludedElements: a set of nodes/edges that should be excluded to avoid infinite loops
    path: an individual path through which a transitive relationship can be computed.

    Output:
    a set of transitive relationships (directed paths) from the fromClass to toClasses


    public ISet findTransitiveRelationshipsForClass(IClass fromClass, ISet toClasses, ISet excludedElements, ISequence path)
    {
    if (fromClass == null || toClasses == null || toClasses.isEmpty())
    {
    return new MSet();
    }
    if (path.size() > 5)
    {
    new WinMsgBoxDlg("ERROR in PartialTransitiveReasoning", "size of path too long").ShowDialog();
    throw new RuntimeException("ERROR in PartialTransitiveReasoning: size of path too long");
    }

    ISet transitiveRelationships = new MSet();

    IRelationship transitiveRelationship = findTransitiveRelationship(path);
    if (transitiveRelationship == null && path.size() == 5)
    {
    new WinMsgBoxDlg("ERROR in PartialTransitiveReasoning", "size of path too long").ShowDialog();
    }
    if (transitiveRelationship instanceof AntiRelationship)
    {
    return transitiveRelationships;
    }
    else if (toClasses.contains(fromClass))
    {
    if (transitiveRelationship != null)
    {
    transitiveRelationships.insert(transitiveRelationship);
    }
    return transitiveRelationships;
    }
    else
    {
    if (transitiveRelationship != null)
    {
    path = new MSequence(new Object[]{path.get(0), transitiveRelationship, path.get(path.size()-1) });
    }

    IIterator relationships = fromClass.getRelationships().iterator();
    while (relationships.hasNext())
    {
    IRelationship relationship = (IRelationship) relationships.next();
    if (relationship != null && !excludedElements.contains(relationship) && !relationship.getIsDerived())
    {
    IIterator classes = relationship.getClassifiers().excluding(fromClass).iterator();
    while (classes.hasNext())
    {
    IClass intermediateClass = (IClass) classes.next();
    if (!excludedElements.contains(intermediateClass))
    {
    ISequence extendedPath = path.toSequence();
    extendedPath.insert(relationship);
    extendedPath.insert(intermediateClass);
    transitiveRelationships.insertAll( findTransitiveRelationshipsForClass(intermediateClass, toClasses, excludedElements.including(intermediateClass), extendedPath) );
    }
    }
    }
    }

    return transitiveRelationships;
    }
    }


  • Redking

    Can you please post repro code

    Thanks,

    Varun



  • jcseth

    Hi Varun,

    Thank you for your response. But what is a "repro code" I have some snapshots showing OutOfMemoryException in some .dll. Do you need that, or you need the code of the recursive method that I suspected Both of them are available.

    Cheers,

    SunnDay


  • Help: how can I avoid the System.OutOfMemoryException?