Results 1 to 15 of 15

Thread: Where would I start looking for a memory leak?

  1. #1

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Where would I start looking for a memory leak?

    There are 50 or so users of my application in-house at our company. They start it in the morning and run it all day long, 8:00 a.m. - 4:30 p.m. If my application is crashing for a few users mid-afternoon saying out of memory exception, is it me? How would I even begin to find this out?
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,344

    Re: Where would I start looking for a memory leak?

    A memory leak is something specific and, given the memory management in .NET, you're probably not experiencing one. The very first thing to do is examine all the information that the exception provides. Is it happening at the same place every time or within the same general task every time?

  3. #3

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    I will have the users capture the detailed info and send it to me so I can start keeping track and looking for a pattern. It doesn't happen regularly or frequently, so I may not post back for some time. Thanks for your idea.
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  4. #4

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    So the exception hasn't occurred (that they're telling me about) but someone was looking at Task Manager while running my application and noticed every time the "case" form was opened and closed, memory kept increasing. It didn't decrease when the case form was closed. The case form is busy and fully of data. But a lot of it is split out into tabs with datagrids. I only load the grids when the tabs are opened. I do have a static class with methods this form calls. But unless the static class is loading and keeping a lot of data around, is this a problem?

    Conversely, I opened and closed over and over a form that we use to send a page to an employee. It also kept growing but after my last close and after leaving the app alone for several minutes, the memory % went back down.

    The memory right now is up to 127.9 Mb and if I opened the case form more times it would grow more and stay.

    So I am not sure what I can do to free the memory the case form seems to be hanging onto.
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  5. #5
    PowerPoster
    Join Date
    Nov 2017
    Posts
    3,138

    Re: Where would I start looking for a memory leak?

    Super general suggestion since you've only provided super general details:

    Create a test project that mimics the functionality of that Case form, make sure that you can reproduce the accumulation of memory usage in said project, slice up the functionality of that form into various "sections", start commenting out some of those sections until the memory increase no longer takes place, and then either post the relevant code here that seems to be the culprit or if you can't do that for technical/copyright/confidentiality reasons hopefully you can track it down on your own.

  6. #6

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    [Deleting - somehow posted the same things as 12:40]
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  7. #7

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    I have a dump of the exception - it just happened to somebody. Is there anything useful in there?
    And thanks, OptionBase1. I am thinking how to cut it down and start cutting parts out to isolate the problem.
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  8. #8

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    Here is the exception of the dump I referred to last post:
    frmJobEntry3 is the case form.

    System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
    at System.Collections.Generic.List`1.set_Capacity(Int32 value)
    at System.Collections.Generic.List`1.EnsureCapacity(Int32 min)
    at System.Collections.Generic.List`1.Add(T item)
    at DevExpress.XtraSpellChecker.SpellCheckerDictionaryBase.AddWordToDoubleMetaphoneIndexes(String word, Int32 index)
    at DevExpress.XtraSpellChecker.SpellCheckerDictionaryBase.FillDoubleMetaphoneIndexes()
    at DevExpress.XtraSpellChecker.SpellCheckerDictionaryBase.OnDictionaryChanged()
    at DevExpress.XtraSpellChecker.SpellCheckerISpellDictionary.LoadFromStream(Stream dictionaryStream, Stream grammarStream, Stream alphabetStream)
    at XXX.OperationSpellCheck.LoadISpellDictionaries(SpellChecker spellChecker1)
    at XXX.OperationSpellCheck.LoadDictionariesAndSetupSpellChecker(SpellChecker spellChecker1)
    at XXX.frmJobEntry3.frmJobEntry3_Load(Object sender, EventArgs e)

    Spellcheck is a somewhat new function I added, so that's kind of suspicious, but I don't see how a dictionary could keep eating up memory.
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  9. #9
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,344

    Re: Where would I start looking for a memory leak?

    So how exactly are you loading this spell-checking dictionary? Is there any way to specify an expected capacity because would make loading that internal List more efficient.

  10. #10

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    I am posting my code. In parallel, I will remove the dictionary from my local copy of the code and open/close the form and watch the memory usage in Task Manager.

    Code:
        public class OperationSpellCheck
        {
    
            public void LoadDictionariesAndSetupSpellChecker(SpellChecker spellChecker1)
            {
                LoadISpellDictionaries(spellChecker1);
    
                spellChecker1.Culture = CultureInfo.InvariantCulture;
                spellChecker1.SpellCheckMode = SpellCheckMode.AsYouType;
            }
    
    
            private void LoadISpellDictionaries(SpellChecker spellChecker1)
            {
                spellChecker1.Dictionaries.Clear();
    
                // The ISpell Dictionary
                SpellCheckerISpellDictionary dictionary = new SpellCheckerISpellDictionary();
                Stream affStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("XXX.Dictionaries.english.aff");
                Stream dicStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("XXX.Dictionaries.american.xlg");
                Stream alphStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("XXX.Dictionaries.EnglishAlphabet.txt");
                // Dictionary, Grammar, Alphabet
                dictionary.LoadFromStream(dicStream, affStream, alphStream);
                spellChecker1.Dictionaries.Add(dictionary);
    
                LoadCustomDictionary(spellChecker1);
            }
    
            private void LoadCustomDictionary(SpellChecker spellChecker1)
            {
                SpellCheckerCustomDictionary customDictionary = new SpellCheckerCustomDictionary();
                string path =
                    System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "XXX 2.0");
                customDictionary.AlphabetPath = path + @"\Dictionaries\EnglishAlphabet.txt";
                customDictionary.DictionaryPath = path + @"\Dictionaries\CustomEnglish.dic";
                customDictionary.Culture = CultureInfo.InvariantCulture;
                spellChecker1.Dictionaries.Add(customDictionary);
            }
        }
    Also, LoadDictionariesAndSetupSpellChecker() has 14 references to it, so it looks like if I am doing something wrong here it could cause problems with so many callers in!
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  11. #11

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    It could also be this:

    Code:
            private void InitializeComponentSpellCheck()
            {
                spellChecker1 = new SpellChecker();
                spellChecker2 = new SpellChecker();
                spellChecker3 = new SpellChecker();
                spellChecker4 = new SpellChecker();
                spellChecker5 = new SpellChecker();
    
                optionsSpelling1 = new OptionsSpelling();
                optionsSpelling2 = new OptionsSpelling();
                optionsSpelling3 = new OptionsSpelling();
                optionsSpelling4 = new OptionsSpelling();
                optionsSpelling5 = new OptionsSpelling();
    
                spellChecker1.CheckAsYouTypeOptions.CheckControlsInParentContainer = true;
                spellChecker1.Culture = new CultureInfo("en-US");
                spellChecker1.ParentContainer = meComplaint;
                spellChecker1.SetShowSpellCheckMenu(meComplaint, true);
                spellChecker1.SetSpellCheckerOptions(meComplaint, optionsSpelling1);
    
                spellChecker2.CheckAsYouTypeOptions.CheckControlsInParentContainer = true;
                spellChecker2.Culture = new CultureInfo("en-US");
                spellChecker2.ParentContainer = meAccessInfo;
                spellChecker2.SetShowSpellCheckMenu(meAccessInfo, true);
                spellChecker2.SetSpellCheckerOptions(meAccessInfo, optionsSpelling2);
    
                spellChecker3.CheckAsYouTypeOptions.CheckControlsInParentContainer = true;
                spellChecker3.Culture = new CultureInfo("en-US");
                spellChecker3.ParentContainer = meResolution;
                spellChecker3.SetShowSpellCheckMenu(meResolution, true);
                spellChecker3.SetSpellCheckerOptions(meResolution, optionsSpelling3);
    
                spellChecker4.CheckAsYouTypeOptions.CheckControlsInParentContainer = true;
                spellChecker4.Culture = new CultureInfo("en-US");
                spellChecker4.ParentContainer = meInternalNotes;
                spellChecker4.SetShowSpellCheckMenu(meInternalNotes, true);
                spellChecker4.SetSpellCheckerOptions(meInternalNotes, optionsSpelling4);
    
                spellChecker5.CheckAsYouTypeOptions.CheckControlsInParentContainer = true;
                spellChecker5.Culture = new CultureInfo("en-US");
                spellChecker5.ParentContainer = meShipInstructions;
                spellChecker5.SetShowSpellCheckMenu(meShipInstructions, true);
                spellChecker5.SetSpellCheckerOptions(meShipInstructions, optionsSpelling5);
    
            }
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  12. #12

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    There is perhaps a problem with the DevExpress dictionary!

    Am looking into that now!
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  13. #13

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    So...there was a problem with the DevExpress Dictionary and they had updates in releases 15.2.15, 16.1.8, 16.2.3.
    Then apparently the problem was re-introduced and they had updates 17.2.10, 18.1.6, 18.2.3.
    I had version 17.2. Maybe I should have just gotten the "official update" but I went hog wild and upgraded to v19.1, their latest (except for the beta version, no thanks).
    I would be surprised if it was being reintroduced again, but I am still seeing memory get allocated and not freed.
    So I am waiting to hear from the vendor.
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  14. #14

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    I've been reading something over and over to see between the lines what I am missing. Here is a summary of what's happened in the past few days. The vendor looked into the possibility of their spellcheck component having a memory leak. They also looked into my use of it and a class that I wrote possibly having a memory leak. The answer is no (if I'm understanding their reply). What they did point out is...

    I found that the OptionsSpelling, OperationSpellCheck and SpellChecker objects are placed into the finalizer queue. So, these objects will be collected later depending on the garbage collector strategy. Refer to the What are the Finalizer Queue and Control+ThreadMethodEntry? article for clarification.

    So it sounds like I'm creating and destroying objects as I should but while waiting around for GC to kick in we are running out of memory.
    OptionsSpelling and SpellChecker are theirs; OperationSpellCheck is mine.

    The link I put in bold up there is a StackOverflow discussion. https://stackoverflow.com/questions/...eadmethodentry

    StackOverflow said don't leave these lines of code in your code but try them out. I did, and I saw the memory staying pretty constant as I opened and closed the form in my app that uses specllcheck and its dictionaries.
    Code:
    System.GC.Collect();
    System.GC.WaitForPendingFinalizers(); // this method may block while it runs the finalizers
    System.GC.Collect();
    So if I'm not supposed to keep this code but without it I'm running out of memory, I'm not sure what options I'm left with.
    Here is a link to my discussion with DX support. It's long but what's relevant is today and the sample she posted, which she assembled from snippets I passed along. Her sample is my code and if there's no memory leak but memory is getting allocated and held onto, what is the solution? https://www.devexpress.com/Support/C...eak-is-it-back
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

  15. #15

    Thread Starter
    PowerPoster MMock's Avatar
    Join Date
    Apr 2007
    Location
    Driving a 2018 Mustang GT down Route 8
    Posts
    4,478

    Re: Where would I start looking for a memory leak?

    And please allow me to throw out this question which I hope isn't "stupid" - my application is click once so everyone downloads it to their own PC. Can GC be running differently on different users PC's? So if user A and user B are doing the exact same operations one could run out of memory while the other does not?

    If this is the case, why is the exception happening? Does the GC not know there's memory it could use and is that under my control?

    Garbage collection occurs when one of the following conditions is true:

    The system has low physical memory. This is detected by either the low memory notification from the OS or low memory indicated by the host.

    The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This threshold is continuously adjusted as the process runs.

    The GC.Collect method is called. In almost all cases, you do not have to call this method, because the garbage collector runs continuously. This method is primarily used for unique situations and testing.
    Excerpted from https://docs.microsoft.com/en-us/dot...n/fundamentals
    There are 10 kinds of people in this world. Those who understand binary, and those who don't.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width