.Net 2.0 Windows Service зависает при сборке мусора - PullRequest
5 голосов
/ 03 мая 2011

Я написал службу Windows .Net (2.0), используемую для отправки пейджинговых сообщений пользователям (через последовательный порт на стороннее оборудование).

Служба периодически запрашивает базу данных (OSI PI Historian), анализирует значения и решает, отправлять ли сообщение на основе разбираемых значений.

Служба использует объект поиска (значения которого поступают из базы данных SQL Server и обновляются каждую минуту) для получения значений адресов пользователя и строки сообщения для отправки.

Служба использует несколько Threading.Timers для запуска периодических вызовов базы данных и отправки сообщений.

Служба установлена ​​на компьютере с Windows 2003, на котором установлен .Net 2 SP2.

Служба работает нормально около недели, а затем зависает. В журнале не регистрируется никаких исключений (log4net).

Я получил несколько дампов с сервера, и все они имеют одинаковые характеристики - поток вызывает GC, но зависает бесконечно :

06aaf06c 7c827b99 77e61d1e 00004acc 00000000 ntdll!KiFastSystemCallRet
06aaf070 77e61d1e 00004acc 00000000 00000000 ntdll!ZwWaitForSingleObject+0xc
06aaf0e0 79e8c5f9 00004acc ffffffff 00000000 kernel32!WaitForSingleObjectEx+0xac
06aaf124 79e8c52f 00004acc ffffffff 00000000 mscorwks!PEImage::LoadImage+0x1af
06aaf174 79e8c54e ffffffff 00000000 00000000 mscorwks!CLREvent::WaitEx+0x117
06aaf188 79f2f88f ffffffff 00000000 00000000 mscorwks!CLREvent::Wait+0x17
06aaf1a8 79f2f8ca 7a3b9020 00000000 ffffffff mscorwks!SVR::gc_heap::user_thread_wait+0x50
06aaf1b8 79f2f806 00000000 7a3b8b18 00080101 mscorwks!WKS::gc_heap::wait_to_proceed+0xe
06aaf1cc 79f92f5a 00000000 00000000 00000000 mscorwks!WKS::gc_heap::garbage_collect+0x247
06aaf1f8 79f94e26 00000000 00000000 00000030 mscorwks!WKS::GCHeap::GarbageCollectGeneration+0x1a9
06aaf284 79f926ce 052c75c8 00000030 00000000 mscorwks!WKS::gc_heap::try_allocate_more_space+0x15b
06aaf298 79f92769 052c75c8 00000030 00000000 mscorwks!WKS::gc_heap::allocate_more_space+0x11
06aaf2b8 79e73291 052c75c8 0000002e 00000000 mscorwks!WKS::GCHeap::Alloc+0x3b
06aaf2d4 79e7d8d4 0000002e 00000000 00000000 mscorwks!Alloc+0x60
06aaf310 79e99056 0000000f b456b75e 00001ce3 mscorwks!SlowAllocateString+0x29
06aaf3b4 792bb2c1 00000000 0108082b 00001f40 mscorwks!FramedAllocateString+0xa1
    Stack shortened for bravity...

Управляемый стек:

ESP       EIP     
06aaf364 7c82847c [HelperMethodFrame: 06aaf364] 
06aaf3bc 792bb2c1 System.String.CreateStringFromEncoding(Byte*, Int32, System.Text.Encoding)
06aaf3dc 792aaf2a System.Text.EncodingNLS.GetString(Byte[], Int32, Int32)
06aaf3fc 6522d131 System.Data.SqlClient.TdsParserStateObject.ReadStringWithEncoding(Int32, System.Text.Encoding, Boolean)
06aaf41c 656ca93e System.Data.SqlClient.TdsParser.ReadSqlStringValue(System.Data.SqlClient.SqlBuffer, Byte, Int32, System.Text.Encoding, Boolean, System.Data.SqlClient.TdsParserStateObject)
06aaf448 6522d925 System.Data.SqlClient.TdsParser.ReadSqlValue(System.Data.SqlClient.SqlBuffer, System.Data.SqlClient.SqlMetaDataPriv, Int32, System.Data.SqlClient.TdsParserStateObject)
06aaf474 656208b7 System.Data.SqlClient.SqlDataReader.ReadColumnData()
06aaf484 65620962 System.Data.SqlClient.SqlDataReader.ReadColumn(Int32, Boolean)
06aaf4b4 65221415 System.Data.SqlClient.SqlDataReader.GetValueInternal(Int32)
06aaf4c8 652213af System.Data.SqlClient.SqlDataReader.GetValue(Int32)
06aaf4f8 65220aec System.Data.SqlClient.SqlDataReader.get_Item(System.String)
06aaf504 03616b81 AlarmEventCollator.DataAccess.GetAllAlarmDetails()
06aaf564 03616a28 AlarmEventCollator.AlarmBuilder.buildLookups()
06aaf590 0361aa89 AlarmEventCollator.AlarmBuilder.pollLookups(System.Object)
06aaf5d0 792a83ff System.Threading._TimerCallback.TimerCallback_Context(System.Object)
06aaf5d8 792e019f System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
06aaf5f0 792a836b System.Threading._TimerCallback.PerformTimerCallback(System.Object)
06aaf77c 79e71b4c [GCFrame: 06aaf77c] 

GC обычно происходит в методах анализа базы данных. Кажется, что все остальные управляемые потоки зависают, что соответствует процессу GC.

Буду признателен за любые указатели. Более подробная информация доступна по запросу.

1 Ответ

2 голосов
/ 18 августа 2011

Сколько потоков GC у нас в .NET-процессе, выполняющем версию GC для сервера на двухъядерном компьютере?

Два, по одному на процессор или, вернее, по одному на логический процессор, поэтому было бы 4, если бы он был гиперпоточным. В процессе, выполняющем версию GC для рабочей станции, у нас не было бы выделенных потоков GC, вместо этого сборка мусора выполняется в потоке, инициирующем GC, поскольку нет смысла переключаться на другой поток для сбора мусора, когда у вас есть только один процесс / один Нить делает GC.

У Криса Лиона есть хорошая статья о режимах GC, а также интересный пост о переходах в режимы GC в Orcas.

Почему это важно для вас? Поскольку разные режимы GC оптимизированы для разных целей, использование вашей памяти, задержка GC и т. Д. Могут сильно различаться в зависимости от того, какой режим GC вы используете. Например, служба Windows по умолчанию получает GC для рабочей станции, но если объем обработки (много недолговечных распределений) велик, вам, вероятно, будет гораздо лучше запустить GC на сервере для использования памяти и производительности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...