Що не так у використанні GC.Collect ()?


103

Хоча я розумію серйозні наслідки гри з цією функцією (або, принаймні, так я вважаю), я не розумію, чому це стає однією з таких речей, якими поважні програмісти ніколи не користуються, навіть ті, хто навіть не знає для чого це.

Скажімо, я розробляю додаток, де використання пам’яті дуже різниться залежно від того, що робить користувач. Життєвий цикл програми можна розділити на два основні етапи: редагування та обробка в режимі реального часу. На етапі редагування припустімо, що створюються мільярди чи навіть трильйони об’єктів; деякі з них невеликі, а деякі - ні, деякі можуть мати фіналізатори, а деякі - ні, і припустимо, їх тривалість життя варіюється від дуже кількох мілісекунд до довгих годин. Далі користувач вирішує перейти на етап реального часу. На даний момент, припустимо, що ефективність відіграє фундаментальну роль і найменша зміна в потоці програми може призвести до катастрофічних наслідків. Створення об'єктів потім зводиться до мінімально можливого за допомогою об’єктних пулів і подібних, але потім, GC несподівано звучить і кидає все, і хтось гине.

Питання: Чи в цьому випадку не було б розумним дзвонити GC.Collect () перед тим, як перейти на другий етап?

Зрештою, ці два етапи ніколи не перетинаються один з одним, і вся оптимізація та статистика, яку можна було б зібрати в GC, тут не дасть користі ...

Примітка. Як дехто з вас зазначав, .NET може бути не найкращою платформою для такого додатка, але це виходить за рамки цього питання. Наміром є уточнення, чи може виклик GC.Collect () покращити загальну поведінку / продуктивність програми чи ні. Ми всі згодні з тим, що обставини, за яких ви зробили б таке, є вкрай рідкісними, але знову ж таки, GC намагається здогадуватися і робить це ідеально добре протягом більшої частини часу, але це все одно про здогадки.

Дякую.


24
"найменша зміна в потоці програми може призвести до катастрофічних наслідків ... хтось може загинути" - ви впевнені, що C # .NET достатньо детермінований для ваших цілей?
Стів Джессоп

4
Ні Windows, ні .NET не є платформами в реальному часі, і тому ви не можете гарантувати показники продуктивності, принаймні, недостатньо, щоб ризикувати людськими життями. Я погоджуюся з одним, що ви або перебільшуєте, або недбало.
Серхіо Акоста

3
LOL в "одній з цих речей, яку поважні програмісти ніколи не використовуватимуть, навіть ті, хто навіть не знає, для чого це"! Програмісти, які використовують речі, не знаючи, чому навряд чи є найбільш поважними у моїй книзі. :)
Даг

Відповіді:


87

З блогу Ріко ...

Правило №1

Не варто.

Це справді найважливіше правило. Справедливо сказати, що більшість звичаїв GC.Collect () - це погана ідея, і я детально описував це у початковій публікації, тому я не повторю все це тут. Тож перейдемо до ...

Правило №2

Подумайте про те, щоб зателефонувати в GC.Collect (), якщо якась неповторювана подія щойно трапилася, і ця подія, ймовірно, призвела до загибелі багатьох старих об'єктів.

Класичним прикладом цього є те, якщо ви пишете клієнтську заявку і ви показуєте дуже велику і складну форму, яка має багато даних, пов'язаних з нею. Ваш користувач щойно взаємодіяв з цією формою, потенційно створюючи деякі великі об'єкти ... такі речі, як XML-документи, чи великий DataSet-два. Коли форма закриє ці об'єкти, вони мертві, і GC.Collect () поверне пам'ять, пов'язану з ними ...

Так здається, що ця ситуація може підпадати під Правило №2, ви знаєте, що настає момент, коли багато старих об’єктів загинуло, і це не повторюється. Однак не забувайте про розлучення слів Ріко.

Правило №1 повинно перемогти правило №2 без вагомих доказів.

Міряти, міряти, міряти.


9
Я б сказав, що це лише стара річ. Ніщо не є насправді поганим чи небезпечним, якщо ви знаєте, що робите, і тому знаєте, коли і як це зробити, а також це побічні ефекти. Такі речі, як ніколи, ніколи не використовуйте xxxx, щоб їх захистити від нерозумних програмістів: D
Хорхе Кордоба


Я не кажу, що використання GC.Collect є гарною практикою. Але іноді це швидкий спосіб вирішити питання, не знаючи його реальної причини. Я потворний, я знаю, але це працює, і мені здається, це не поганий підхід, особливо коли не так багато часу, щоб з'ясувати першопричину проблеми, а твій начальник стоїть позаду тебе ... ти знаєш.
Мовчазний прикордонник

58

Якщо ви називаєте GC.Collect () у виробничому коді, ви по суті заявляєте, що знаєте більше, ніж автори GC. Це може бути так. Однак зазвичай це не так, і тому сильно не рекомендується.


3
Це дуже правда, але я не знаю, чи могли вони зробити припущення, які стосуються всіх подій.
MasterMastic

2
@Ken Ні, вони не можуть. Але ви в цьому вигідніші? Або ви збираєтеся писати код, передбачаючи конкретне обладнання, конкретну версію ОС тощо? Коефіцієнт болю / посилення на цьому рівні занадто високий.
Даг

2
@TheDag IMO, звичайно, є. Коли я звільняю пам'ять, а що ні, я не дуже переймаюся обладнанням, тому що це завдання ОС для вирішення цього питання. Мене також не хвилює ОС, оскільки у мене є інтерфейс, спільний для всіх тих, для кого я програмую. (наприклад, мені байдуже, чи це Windows, Mac чи Linux: коли я виділяю / звільняю пам'ять в C / C ++, це новий / видалити malloc / dealloc). Я завжди можу помилятися, тому сміливо виправте мене.
MasterMastic

@MasterMastic mallocмає лише дуже простий інтерфейс, і його реалізація може досить відрізнятися від значення. Все залежить від того, яку проблему ви намагаєтеся вирішити. Якби mallocбуло "досить добре", вам би не потрібне об'єднання буфера, чи не так? Розробка C / C ++ рясніє прикладами, коли ви намагаєтесь вдруге відгадати ОС / час виконання / бібліотеки, тому що ви знаєте краще (а іноді й справді). Багато критично важливих для роботи додатків уникають використання системних розподільників / виконання. Ігри, які використовуються для попереднього розподілу всієї пам'яті при запуску (масиви постійного розміру тощо).
Луань

24

То як щодо того, коли ви використовуєте COM-об’єкти, такі як MS Word або MS Excel від .NET? Без виклику GC.Collectпісля випуску об’єктів COM ми виявили, що екземпляри програми Word або Excel все ще існують.

Насправді код, який ми використовуємо:

Utils.ReleaseCOMObject(objExcel)

' Call the Garbage Collector twice. The GC needs to be called twice in order to get the
' Finalizers called - the first time in, it simply makes a list of what is to be finalized,
' the second time in, it actually does the finalizing. Only then will the object do its 
' automatic ReleaseComObject. Note: Calling the GC is a time-consuming process, 
' but one that may be necessary when automating Excel because it is the only way to 
' release all the Excel COM objects referenced indirectly.
' Ref: http://www.informit.com/articles/article.aspx?p=1346865&seqNum=5
' Ref: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

То це було б неправильне використання сміттєзбірника? Якщо так, як змусити об'єкти Interop померти? Крім того, якщо він не призначений для використання , як це, чому в GC«S Collectметод навіть Public?


3
Це призвело б до чудового нового питання StackOverflow, тобто: Як викорінити екземпляри COM без виклику GC. Що стосується некерованих кругових посилань. Це одне з викликів, які змусили мене насторожитися над оновленням надбудови VB6 Outlook до C #. (Ми провели багато роботи над розробкою моделей кодування та тестових випадків на стороні VB, які гарантували, що посилання на COM були вбиті детермінованим способом, коли вони більше не потрібні).
rkagerer

2
Якщо це стосується об'єктів COM взагалі, можливо, це правильний сценарій. Але поза увагою, я б сказав, що проблема, ймовірно, ви використовуєте клієнтську програму, розроблену для інтерактивного робочого столу як COM-сервера. З бази знань MSDN: "Microsoft в даний час не рекомендує і не підтримує автоматизацію програм Microsoft Office від будь-якого непридатного, неінтерактивного клієнтського додатка чи компонента (включаючи ASP, ASP.NET, DCOM та NT Services), оскільки Office може проявляти нестабільну поведінку та / або тупик, коли Office працює в цьому середовищі. "
Даг

2
@TheDag - Microsoft може не рекомендувати, але багатьом з нас довелося перенести старий код VB6 з офісним інтеропом до .Net windows apps. Я витратив місяці роботи, поки нарешті позбувся всіх невидимих ​​висячих посилань на великий проект перетворення VB6 в .Net. Навчаємось випускати у зворотному порядку присвоєння та проводити місцеві рефлекси на КОЖЕН єдиний об'єкт com, включаючи колекції.
Діб

15

Ну, GC - це одна з тих речей, з якими я маю стосунки кохання / ненависті. Ми це ламали в минулому через VistaDB і блогували про нього. Вони це виправили, але потрібен ВЕЛИКИЙ час, щоб отримати виправлення у них подібних речей.

GC складний, і один розмір, який відповідає всім підходам, дуже-дуже важко зняти щось таке велике. МС зробила це досить непогано, але обдурити ГК можна часом.

Загалом, ви не повинні додавати, Collectякщо ви не знаєте, що за фактом ви просто скинули тонну пам’яті, і це піде в кризу середнього життя, якщо GC не очистить її зараз.

Можна викрутити всю машину низкою поганих GC.Collectтверджень. Необхідність у заяві збирання майже завжди вказує на більшу основну помилку. Витік пам'яті зазвичай пов'язаний із посиланнями та нерозумінням того, як вони працюють. Або використання IDisposableоб'єктів, які цього не потребують, і навантаження на GC значно більше.

Уважно стежте за відсотком часу, проведеного в GC, за допомогою лічильників продуктивності системи. Якщо ви бачите, що ваш додаток використовує 20% або більше його часу в GC, у вас є серйозні проблеми управління об’єктом (або ненормальна схема використання). Ви хочете завжди мінімізувати час, який витрачає GC, оскільки це пришвидшить весь ваш додаток.

Важливо також зазначити, що GC відрізняється на серверах, ніж на робочих станціях. Я бачив цілу низку невеликих труднощів розслідувати проблеми з людьми, які не тестують обох (або навіть не знають, що їх двоє).

І щоб бути максимально повною у моїй відповіді, ви також повинні перевірити Mono, якщо ви також орієнтуєтесь на цю платформу. Оскільки це зовсім інша реалізація, вона може зіткнутися з абсолютно різними проблемами, ніж впровадження МС.


Винуватець часто події. Щоразу, коли метод обробника використовується як обробник подій, видавець події має посилання на підписника через делегата події. Єдиний "простий" спосіб уникнути проблем із цим - використовувати лише видавців, які є максимум такими ж довгоживучими, як і передплатники (наприклад, TextBox, який публікує подію, оброблювану формою, що містить форму, не є проблемою, оскільки текстове поле не передбачається жити поза формою). Приклад сценарію проблеми: модель Singleton, тимчасові подання, що обробляють події моделі.
Даг

5
Як можна накрутити всю машину?
Адам Р. Грей

13

Бувають ситуації, коли це корисно, але взагалі цього слід уникати. Ви можете порівняти це з GOTO або їздити на мопеді: ви робите це, коли вам потрібно, але ви не повідомляєте про це своїм друзям.


12

З мого досвіду, ніколи не було доцільно телефонувати в GC.Collect () у виробничому коді. При налагодженні, так, переваги допомагають уточнити можливі витоки пам'яті. Я думаю, що моя основна причина полягає в тому, що GC був написаний та оптимізований програмістами набагато розумнішим, ніж я, і якщо я доходжу до точки, яку я відчуваю, що мені потрібно викликати GC.Collect (), це поняття, що я пішов шляхом десь. У вашій ситуації це не здається, що у вас насправді є проблеми з пам’яттю, просто вас турбує, яка нестабільність колекція принесе вашому процесу. Побачивши, що він не буде очищати об'єкти, що ще використовуються, і що він дуже швидко адаптується як до зростаючих, так і до нижчих вимог, я думаю, вам не доведеться турбуватися про це.


10

Однією з найважливіших причин викликати GC.Collect () є те, що ви тільки що провели значну подію, яка створює багато сміття, наприклад, те, що ви описуєте. Виклик GC.Collect () може бути хорошою ідеєю тут; інакше GC може не зрозуміти, що це була подія "разово".

Звичайно, вам слід це профільно переконатися.


9

Ну, очевидно, ви не повинні писати код з вимогами в режимі реального часу мовами з вивезенням сміття в реальному часі.

У випадку з чітко визначеними етапами не виникає проблем із запуском сміттєзбірника. Але цей випадок вкрай рідкісний. Проблема полягає в тому, що багато розробників намагаються використати це для вирішення проблем, пов'язаних з оформленням паперу, в культовому стилі, і додавання його без розбору спричинить проблеми з роботою.


Правда. Але ціннісні автоматизовані тести, здатні виявити стан помилки "об'єкт, не придатний для вивезення сміття, але повинен бути", був би цінним. I це може бути досягнуто за допомогою комбінації заводської логіки, логіки деструктора та GC.Collect. Наприклад, ваш клас Entity має властивість IObjectTracker, як правило, нульове, але присвоєне заводом об'єкта перевірки. Фабрика також повідомляє трекер про народження об'єкта, тоді як деструктор повідомляє про смерть. Якщо ви можете знати, що "деструктор виконав усі об'єкти, що збирають сміття", ви можете перевірити стан трекера, щоб виявити витоки.
Даг

7

Виклик GC.Collect () змушує CLR зробити прогулянку стеком, щоб побачити, чи можна справді звільнити кожен об'єкт, перевіривши посилання. Це вплине на масштабованість, якщо кількість об’єктів буде великою, а також, як відомо, занадто часто викликає збирання сміття. Довіряйте CLR і нехай сміттєзбірник працює сам, коли це доречно.


2
Ви не тільки викликаєте ходу стека, але головна нитка ваших додатків (і будь-які створені ними дочірні нитки) заморожені, щоб GC міг ходити по стеку. Чим більше часу ваш додаток проводить в GC, тим більше часу він витрачає замороженим.
Скотт Дорман

3
Мене більше хвилює App Crash через виняток поза пам'яттю, ніж повільна продуктивність, оскільки додаток / GC викидає речі, які більше не потрібні. Хтось знає, чому Microsoft, здається, викидає виняток OOM без ПЕРШОГО викидання сміття? (Без цього ЗАБЕЗПЕЧНОГО кроку - або, принаймні, пояснення, чому цей крок не робиться спробою перед тим, як кинути виняток з МОМ. Я не впевнений, що я маю віру в те, що відбувається "автоматично" так, як вони повинні. "
Wonderbird

6

Infact, я не думаю, що це дуже погана практика називати GC.Collect.
Можуть бути випадки, коли нам це потрібно. Наприклад, у мене є форма, яка запускає потік, яка відкриває різні таблиці в базі даних, витягує вміст у поле BLOB у тимчасовий файл, зашифровує файл, потім читає файл у бінарний потік і повертається у BLOB поле в іншій таблиці.

Вся операція займає досить багато пам’яті, і невідомо про кількість рядків та розмір вмісту файлів у таблицях.

Я часто отримував OutofMemory Exception часто, і думав, що було б розумно періодично запускати GC.Collect на основі лічильної змінної. Я збільшую лічильник і коли досягнуто заданого рівня, GC викликається збирати будь-яке сміття, яке, можливо, утворилося, та відновлювати будь-яку пам'ять, втрачену через непередбачені витоки пам'яті.

Після цього я думаю, що це працює добре, принаймні, не виняток !!!
Я дзвоню таким чином:

var obj = /* object utilizing the memory, in my case Form itself */
GC.Collect(GC.GetGeneration(obj ,GCCollectionMode.Optimized).

5

Відповідно до .net, час, необхідний для вивезення сміття, набагато сильніше пов'язаний із кількістю речі, яка не є сміттям, ніж із кількістю речовини, яка є. Дійсно, якщо об'єкт не переорієнтований Finalize(явно, або через деструктор C #), не є цілью a WeakReference, сидить на великій купі об'єктів або є спеціальним якимось іншим способом, пов'язаним з gc, єдине, що ідентифікує пам'ять, у якій він сидить як об'єкт - це наявність укорінених посилань на нього. В іншому випадку функціонування GC є аналогічним вилученню з будівлі всього цінного та динаміцізації будівлі, будівництву нового на місці старого та покладенню в нього всіх цінних речей. Зусилля, необхідні для динамізації будівлі, абсолютно не залежать від кількості сміття всередині нього.

Отже, виклик GC.Collectє сприятливим для збільшення загального обсягу роботи, яку має виконати система. Це затримає появу наступної колекції, але, ймовірно, зробить одразу стільки ж роботи, скільки потрібно було б наступній колекції, коли вона відбудеться; в момент, коли відбудеться наступне збирання, загальна кількість часу, проведеного на збір, буде приблизно такою ж, як і GC.Collectне було викликано, але система накопичила сміття, внаслідок чого наступна збірка потребуватиметься раніше, ніж GC.Collectні називались.

Часи, які я бачу GC.Collectсправді корисними, це коли потрібно вимірювати використання пам'яті деякого коду (оскільки дані про використання пам'яті мають значення лише після колекції), або проаналізувати, який з кількох алгоритмів краще (виклик GC.Collect () перед запуском кожного з декількох фрагментів коду можна допомогти забезпечити послідовний базовий стан). Є кілька інших випадків, коли можна знати речі, які не знає GC, але, якщо ви не пишете однопотокову програму, немає ніякого способу знати, що GC.Collectвиклик, який допоможе структурам даних однієї нитки уникнути "кризи середнього життя" "не спричинило б, щоб дані інших потоків мали" кризи середнього життя ", яких інакше можна було б уникнути.


5

Створення зображень у циклі - навіть якщо ви зателефонуєте утилізувати, пам'ять не буде відновлено. Сміття збирають щоразу. Я перейшов від 1,7 Гб пам’яті свого додатка для обробки фотографій до 24 Мб, а продуктивність відмінна.

Вам потрібно зателефонувати в GC.Collect.


2
Покликання Disposeце не повинно звільнити керовану пам'ять. Ви, здається, не знаєте, як працює модель пам'яті в .NET.
Ендрю Барбер

4

У нас була схожа проблема з тим, що сміттєзбірник не збирає сміття та звільняє пам'ять.

У нашій програмі ми обробляли кілька скромних таблиць Excel за допомогою OpenXML. Електронні таблиці містили десь від 5 до 10 "аркушів" з приблизно 1000 рядками з 14 стовпців.

Програма в 32-бітному середовищі (x86) призведе до аварії з помилкою "поза пам'яттю". Ми дійсно отримали його для запуску в середовищі x64, але ми хотіли кращого рішення.

Ми знайшли його.

Ось кілька спрощених фрагментів коду того, що не працювало і що працювало, коли мова йде про явний виклик колектора сміття для звільнення пам'яті від розміщених об’єктів.

Виклик GC зсередини підпрограми не спрацював. Пам'ять ніколи не відновлювалася ...

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

Перемістивши виклик GC за рамки підпрограми, сміття було зібрано і пам'ять було звільнено.

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
End Sub

Я сподіваюся, що це допомагає іншим, хто розчарується у збиранні сміття .NET, коли, здається, ігнорує дзвінки GC.Collect().

Пол Сміт


4

Нічого поганого в тому, щоб явно закликати колекцію. Деякі люди просто хочуть вірити, що якщо це послуга, що надається постачальником, не сумнівайтеся. О, і всі ці випадкові заморозки в неправильні моменти вашої інтерактивної програми? Наступна версія зробить це краще!

Дозволити фоновому процесу займатися маніпулюванням пам’яттю - це означає, що не потрібно з цим боротися самі. Але це логічно не означає, що для нас найкраще за всіх обставин не впоратися з цим. GC оптимізовано для більшості випадків. Але це логічно не означає, що воно оптимізоване у всіх випадках.

Ви коли-небудь відповідали на відкрите запитання на кшталт "який найкращий алгоритм сортування" з остаточною відповіддю? Якщо так, не торкайтеся GC. Для тих із вас, хто запитав умови або дав відповіді "в даному випадку", ви можете перейти до ознайомлення з GC та коли його активувати.

Потрібно сказати, що у мене в Chrome і Firefox заморожуються додатки, які мене відштовхують, і навіть тоді в деяких випадках пам'ять безперешкодно зростає. Якби вони навчилися викликати сміттєзбірника - або дали мені натисніть кнопку, щоб, коли я починаю читати текст сторінки, я можу натиснути на неї і, таким чином, не зависати протягом наступних 20 хвилин.


2

Я думаю, що ти маєш рацію щодо сценарію, але я не впевнений у API.

Microsoft каже, що в таких випадках слід додавати тиск пам’яті як натяк на GC, що він незабаром повинен виконати збір.


2
Цікаво, але в документації йдеться про те, що AddMemoryPressure слід використовувати, коли "невеликий керований об'єкт виділяє великий об'єм пам'яті, що не управляється". (наголос мій)
Роберт Полсон

2

Що з цим не так? Той факт, що ви вдруге відгадуєте збирач сміття та розподільник пам'яті, які між ними мають набагато більше уявлення про фактичне використання пам’яті вашої програми під час виконання, ніж ви.


1
Евристичний характер сміттєзбірника та той факт, що вони відкрили цю функціональність зовнішньому світу, змушують мене думати про це як про щось корисне, якщо використовувати його там, де воно має бути. Проблема полягає не в тому, щоб використовувати його, а знати, як, де і коли ним користуватися.
Пастка

Не кажучи вже про кращі знання GC про будь-який інший додаток та їх пам’яті. GC узгоджує пам'ять з ОС, і як така впливає наявна фізична пам'ять та всі інші процеси на машині як керовані, так і некеровані. Хоча я сумніваюся, що GC дійсно знає, "коли настав час для збору" за принципом "від конкретного випадку", це, швидше за все, мати кращу стратегію в цілому, ніж ... БУДЬ-ЯК єдине застосування. ;)
Даг

2

Бажання зателефонувати GC.Collect () зазвичай намагається приховати помилки, які ви зробили десь ще!

Було б краще, якщо ви знайдете там, де ви забули викидати речі, які вам більше не потрібні.


5
ось, можливо, узагальнення
MickyD

1

Знизу ви можете профайлювати додаток і побачити, як ці додаткові колекції впливають на речі. Я б пропонував триматися подалі від нього, окрім випадків, коли ви не збираєтеся займатися профілем. GC створений, щоб піклуватися про себе, і в міру розвитку часу вони можуть підвищити ефективність. Ви не хочете, щоб купа коду висіла навколо, що може перешкодити роботі та не мати змоги скористатися цими вдосконаленнями. Існує аналогічний аргумент для використання foreach замість того, що майбутні вдосконалення під обкладинками можуть бути додані до foreach, і ваш код не повинен змінюватися, щоб мати перевагу.


1

Сама .NET Framework ніколи не була розроблена для роботи в режимі реального часу. Якщо вам справді потрібна обробка в режимі реального часу, ви будете використовувати вбудовану мову в режимі реального часу, яка не заснована на .NET, або використовувати .NET Compact Framework, що працює на пристрої Windows CE.


Він міг би використовувати .Net Micro Framework, який розробили для реального часу.
TraumaPony

@TraumaPony: Перевірте діаграму внизу цієї сторінки msdn.microsoft.com/en-us/embedded/bb278106.aspx : Очевидно, що Micro Framework не був розроблений для середовищ у реальному часі. Однак він був розроблений для вбудованих середовищ (як WinCE), але з меншими вимогами до потужності.
Скотт Дорман

1

Найгірше, що буде зроблено, - це змусити вашу програму трохи застигнути. Тож якщо з вами все гаразд, зробіть це. Зазвичай він не потрібний для товстих клієнтських чи веб-додатків із переважно взаємодією користувачів.

Я виявив, що іноді програми з тривалими потоками або пакетні програми отримують виняток OutOfMemory, навіть якщо вони належним чином розміщують об'єкти. Я пам’ятаю, що це обробка транзакцій з базою даних про бізнес; інша - це процедура індексування фонової нитки в товстій програмі для клієнтів.

В обох випадках результат був простим: немає GC.Collect, з пам'яті, послідовно; GC.Колекція, бездоганна продуктивність.

Я спробував це вирішити проблеми з пам'яттю кілька разів, безрезультатно. Я його вийняв.

Якщо коротко, не вкладайте його, якщо ви не отримуєте помилок. Якщо ви помістите його, і це не усуне проблему з пам'яттю, вийміть її назад. Не забудьте перевірити в режимі випуску і порівняти яблука з яблуками.

Єдиний раз, коли справи можуть піти не так, це коли ви ставитесь до цього моралістично. Це не питання цінності; багато програмістів загинули і пішли прямо на небеса з багатьма непотрібними GC.Collects у своєму коді, який пережив їх.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.