Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 | 3 |

 

  Вопрос: GC финализирует объект без причины Добавлено: 01.09.12 20:36  

Автор вопроса:  Programmer

Ответить

  Ответы Всего ответов: 45  

Номер ответа: 31
Автор ответа:
 бзззззьььь



Вопросов: 0
Ответов: 6
 Профиль | | #31 Добавлено: 03.09.12 00:09
финализатор вообще достаточно редкое явление в коде с#..
 обычно всегда хвататет грамотно реализовать IDisposable и освободить там неуправляемые ресурсы


+152

Ответить

Номер ответа: 32
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #32 Добавлено: 03.09.12 00:18
Ну, юзать MemoryStream не обов'язково; таку штуку можна й за допомогою List<byte> реалізувати без особливих додаткових зусиль. Якшо максимальна швидкодія не відіграє вирішальну роль у твоєму задумі. Можна в разі потреби реалізувати просто похідним від Stream, коли треба. Також й без BinaryWriter обійтись, змінивши на BitConverter. Було б надійно, просто, дешево і сердито як кажеться. Дуже заплутаний в тебе код вийшов. В мене час від часу такі проблеми виникають при роботі з багатопоточним кодом.
Разница в скорости огромная. BinaryReader-Writer использовать обязательно.

Ответить

Номер ответа: 33
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #33 Добавлено: 03.09.12 00:25
Если есть какие-то цели, котоыре преследуются кодом, нужно было о них написать, я описал недостатки, присутствующие в коде, а не занимался декомпозицией механизмов работы.

Programmer пишет:
Откуда здесь взятся асинхронному исключению? Или срабатывает эта ветка или далее выполнение как раз и ведет в try-finally.

Асинхронное исключение может произойти в любом месте программы в любой момент времени, в том числе там где я указал.

Ответить

Номер ответа: 34
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #34 Добавлено: 03.09.12 00:32
Programmer пишет:
Профайлер показывает значительный выигрышь. Не было бы тормозов - не было бы и пула.

Это на пуле MemoryStream получен значительный выигрыш?
Менеджер памяти за секунду может инициализировать несколько миллионов таких MemoryStream'ов.

А хранение 5 тысяч объектов в статической переменной приведет к реальному снижению производительности сбокри мусора.

Ответить

Номер ответа: 35
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #35 Добавлено: 03.09.12 00:40
  1. Если есть какие-то цели, котоыре преследуются кодом, нужно было о них написать, я описал недостатки, присутствующие в коде, а не занимался декомпозицией механизмов работы.

Спасибо, но код прекрасно справляется со своими целями, а вопрос был совсем о другом. В один прекрасный момент при вызове Write поле _disposedAt содержит "at ~SimpleDataBuffer", при этом предыдущий вызов Write (на позицию ниже по стэку) был выполнен успешно.

Асинхронное исключение может произойти в любом месте программы в любой момент времени, в том числе там где я указал.
Если кто-то вздумает вызвать Thread.Abort, так тому и быть. Остальные возможные асинхронные исключения неминуемо приведут к немедленному завершению процесса, поэтому не рассматриваются.

Ответить

Номер ответа: 36
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #36 Добавлено: 03.09.12 00:47
Это на пуле MemoryStream получен значительный выигрыш?
Да. В моем коде буфер создается очень часто. ОЧЕНЬ много раз. Профайлер вывел его конструктор на первую строчку.

Ответить

Номер ответа: 37
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #37 Добавлено: 03.09.12 00:51
Что касается количества объектов в пуле - то оно будет расти соразмерно с использованием класса. Мало вероятно, что оно превысит 300-400 инстансов.

Ответить

Номер ответа: 38
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #38 Добавлено: 03.09.12 01:30
Programmer пишет:
Спасибо, но код прекрасно справляется со своими целями, а вопрос был совсем о другом. В один прекрасный момент при вызове Write поле _disposedAt содержит "at ~SimpleDataBuffer", при этом предыдущий вызов Write (на позицию ниже по стэку) был выполнен успешно.


1) Смотри используются ли где-нибудь в программе WeakReference. Это еще один способ когда можно получить доступ к финализированному объекту, правда в очень маленьком окне.
2) Используется ли доступ к другим объектам (в т.ч. на запись, даже неявно). Учитывая что ты нашлепал финализаторов от души, эта ситуация вполне возможна.
3) Сделай разные флаги для фиксации вызовов финализатора и Dispose, чтоб можно было отдельно отследить ситуацию когда каким-то образом была получена ссылка на "финализированный объект" и ссылка на объект, которому был сделан ручной Dispose

Это если говорить в частности.

Если вобщем, то то что я писал выше, выпилить все что касается управления памяти.

Ответить

Номер ответа: 39
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #39 Добавлено: 03.09.12 01:35
Programmer пишет:
Да. В моем коде буфер создается очень часто. ОЧЕНЬ много раз. Профайлер вывел его конструктор на первую строчку.

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

Я был бы благодарен, если бы вы сделали небольшое консольное приложение с демонстарцией того, как пул MemoryStream позволяет существенно выиграть в производительности.

Ответить

Номер ответа: 40
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #40 Добавлено: 03.09.12 22:09
Ты забыл, что у меня еще BinaryReader и BinaryWriter.

Пожалуйста:
Без пула - 8237.
С пулом - 1528.
  1.  
  2.             var array = new byte[] { 1, 2, 3, 4, 5 };
  3.             int count = 10000000;
  4.             Stopwatch sw = StopwatchInt.StartNew();
  5.             for (int i = 0; i <= count; i++)
  6.             {
  7.                 var ms = new MemoryStream();
  8.                 var wr1 = new BinaryWriter(ms);
  9.                 var rr = new BinaryReader(ms);
  10.                 wr1.Write(array, 0, 5);
  11.                 wr1.Close();
  12.                 rr.Close();
  13.                 ms.Dispose();
  14.             }
  15.             Console.WriteLine(sw.ElapsedMilliseconds);
  16.  
  17.             sw = Stopwatch.StartNew();
  18.             var pool = new System.Tuple<MemoryStream, BinaryWriter, BinaryReader>[count + 2];
  19.             var cachedMs = new MemoryStream();
  20.             pool[0] = Tuple.Create(cachedMs, new BinaryWriter(cachedMs), new BinaryReader(cachedMs));
  21.             for (int i = 0; i <= count; i++)
  22.             {
  23.                 MemoryStream ms;
  24.                 BinaryReader rr;
  25.                 BinaryWriter wr1;
  26.                 lock (pool)
  27.                 {
  28.                     var el = pool;
  29.                     ms = el.Item1;
  30.                     wr1 = el.Item2;
  31.                     rr = el.Item3;
  32.  
  33.                     pool = null;
  34.                 }
  35.                 ms.Position = 0;
  36.                 ms.SetLength(0);
  37.                 wr1.Write(array, 0, 5);
  38.                 lock (pool)
  39.                 {
  40.                     pool[i + 1] = System.Tuple.Create(ms, wr1, rr);
  41.                 }
  42.             }
  43.             Console.WriteLine(sw.ElapsedMilliseconds);
  44.             Console.ReadLine();




Смотри используются ли где-нибудь в программе WeakReference. Это еще один способ когда можно получить доступ к финализированному объекту, правда в очень маленьком окне.
Такого нет.
Используется ли доступ к другим объектам (в т.ч. на запись, даже неявно). Учитывая что ты нашлепал финализаторов от души, эта ситуация вполне возможна.
Как видишь, в этом фиинализаторе не используются другие объекты.

Вообще я посмотрел рефлектором MemoryStream и BinaryReader-BinaryWriter и обнаружил, что они ничего не делают в Dispose (в основном только устанавливают флаг disposed), так что без финализатора можно обойтись.

Сделай разные флаги для фиксации вызовов финализатора и Dispose, чтоб можно было отдельно отследить ситуацию когда каким-то образом была получена ссылка на "финализированный объект" и ссылка на объект, которому был сделан ручной Dispose
Раз воспроизвести не получится, придется поверить мне на слово. И вот что я скажу. Когда я только обнаружил ошибку, я добавил установку флага в Dispose, но не в финализатор. Так вот, когда ошибка повторилась, флаг был пустым. Только когда я добавил установку флага в финализатор, флаг оказался установленным при повторении ошибки.

Если снова словлю ошибку - выложу каким образом получена ссылка на объект.

Кстати, можешь рассказать подробнее про твой игровой сервер? Меня интересует, время отклика сервера и частота передачи пакетов для каждого клиента (из 65 000). На каком железе тестировал? Сколько расход ЦП?

Ответить

Номер ответа: 41
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #41 Добавлено: 03.09.12 22:11
Там где начинается курсив дожно быть var el = pool [ i ];

Ответить

Номер ответа: 42
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #42 Добавлено: 04.09.12 02:38
Все, ошибка больше не появляется. Может ты был прав и помогло удаление лишних финализаторов. Утечек памяти нет. Большое спасибо за помощь!

Буду заглядывать в топик - жду ответ на предыдущий пост.

Ответить

Номер ответа: 43
Автор ответа:
 EROS



Вопросов: 58
Ответов: 4255
 Профиль | | #43 Добавлено: 04.09.12 08:03
жду ответ на предыдущий пост.

А какого ответа ты ждешь? Твой бенчмарк лишь показывает что создание 30 млн объектов - это дольше чем не создавать их вообще.. Это и коню понятно..
Что,конкретно, ты тут тестировал?

Ответить

Номер ответа: 44
Автор ответа:
 Programmer



Вопросов: 71
Ответов: 246
 Профиль | | #44 Добавлено: 04.09.12 13:04
Бенчмарк содержит использование монитора для доступа к пулу, очистку стрима, который взят из пула, удаление элемента из пула и его добавление, запись в поток. Т.е. то, что происходит с моим SimpleDataBuffer. Это доказывает необходимость использования пула в моем случае.

Да, не имеет смысл использовать пул для хранения одного единственного MemoryStream, но за компанию с другими объектами - вполне оправданно.

Ответить

Номер ответа: 45
Автор ответа:
 пєтросян



Вопросов: 0
Ответов: 4
 Web-сайт: mmm.sayta.net
 Профиль | | #45
Добавлено: 04.09.12 18:24
помогло удаление лишних финализаторов
отож GC баче шо фіналізатор є, й дума "чіму б мєнє об'єкт нє фіналізіровать?". чим проще - тим надійніше і краще. істіну вам глаголю.

Ответить

Страница: 1 | 2 | 3 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам