Re[9]: Юнит тестирование "памяти"
От: Tom Россия http://www.RSDN.ru
Дата: 20.04.15 15:54
Оценка: +1
FR>Варианты на текущий момент:
FR>1. Берем дотМемори — аттачимся, снимаем сколько угодно снапшотов и препарируем.
Вы шо. Это жеж продакшин! Туда ну никак атачиться низя.

FR>2. Нельзя поставить на продакшен дотМемори из инсталлера? Берем RemoteAgent, копируем на продакшен, запускаем (это экзешничек с wcf сервисом), аттачимся удаленно, см. п.1

FR>Такие варианты совсем не спасают?
Технически можно всё что угодно, практически никто в приличном обществе к продакшину неподпустит.
Народная мудрось
всем все никому ничего(с).
Re[10]: Юнит тестирование "памяти"
От: fedor.reznik  
Дата: 20.04.15 16:11
Оценка:
Здравствуйте, Tom, Вы писали:

FR>>Варианты на текущий момент:

FR>>1. Берем дотМемори — аттачимся, снимаем сколько угодно снапшотов и препарируем.
Tom>Вы шо. Это жеж продакшин! Туда ну никак атачиться низя.

А аттачиться нельзя, потому что замедляет или политики безопасности? А дамп при этом можно?

FR>>2. Нельзя поставить на продакшен дотМемори из инсталлера? Берем RemoteAgent, копируем на продакшен, запускаем (это экзешничек с wcf сервисом), аттачимся удаленно, см. п.1

Tom>Технически можно всё что угодно, практически никто в приличном обществе к продакшину неподпустит.

Но при этом у Вас очевидно есть возможность туда пойти и снять дамп, что несколько нарушает фразу "никто в приличном обществе к продакшину неподпустит"

В теории есть еще третий вариант, мы сейчас обкатываем так называемый self-profiling API, который позволяет оттопырить из приложения условно кнопку — дай мне перформанс снапшот, дай мне мемори снапшот,
на выходе получается файл, который умеет открывать dotMemory или dotTrace, соответственно.
А это уже не сильно отличается от "зайти и снять дамп".
В данный момент такая функциональность доступна по запросу.

Вы не поймите меня не правильно, дампы мы и сами хотим сделать.
Просто хочется понять можно ли помочь большинству тех, кто хочет дампы, уже существующими средствами.
Re[11]: Юнит тестирование "памяти"
От: Tom Россия http://www.RSDN.ru
Дата: 20.04.15 16:26
Оценка: +2
FR>А аттачиться нельзя, потому что замедляет или политики безопасности? А дамп при этом можно?
Атачиться нельзя по многим причинам.
Во первых у меня на продакшине тысяч 10 активных пользователей к серверам обращается и что будет при присоединении профайлера и тем более при сборе снэпшотов никому неизвестно.
Лучшее что может произойти — некоторые клиенты получат таймаутом по башке.
Во вторых кроме как OnDemand бывают OnPremise инсталяции в разных там банках а там сесуриту итп.
А дамп (procdump), при условии клонирования процесса (-r) операция давольно безопасная.

FR>Но при этом у Вас очевидно есть возможность туда пойти и снять дамп, что несколько нарушает фразу "никто в приличном обществе к продакшину неподпустит"

Не нарушает. Ибо дамп в состоянии сделать OPS товарищи, тогда как для работы с профайлером нужна много большая квалификация.

FR>В теории есть еще третий вариант, мы сейчас обкатываем так называемый self-profiling API, который позволяет оттопырить из приложения условно кнопку — дай мне перформанс снапшот, дай мне мемори снапшот,

FR>на выходе получается файл, который умеет открывать dotMemory или dotTrace, соответственно.
FR>А это уже не сильно отличается от "зайти и снять дамп".
FR>В данный момент такая функциональность доступна по запросу.
Мммм для нас бесполезно. Ибо по сути будет означать подключение профайлера.

FR>Вы не поймите меня не правильно, дампы мы и сами хотим сделать.

FR>Просто хочется понять можно ли помочь большинству тех, кто хочет дампы, уже существующими средствами.
Можно.Сделайте дампы
Народная мудрось
всем все никому ничего(с).
Re[12]: Юнит тестирование "памяти"
От: fedor.reznik  
Дата: 20.04.15 16:43
Оценка:
Здравствуйте, Tom, Вы писали:

Ясно, понятно
Еще один "+" в копилочку сделать дампы, еще один "-" в сторону теории, что xcopy exe всегда можно запустить.
Спасибо.
Re[9]: Юнит тестирование "памяти"
От: Tesh США  
Дата: 20.04.15 17:07
Оценка: +1
Здравствуйте, fedor.reznik, Вы писали:

FR>Варианты на текущий момент:

FR>1. Берем дотМемори — аттачимся, снимаем сколько угодно снапшотов и препарируем.
FR>2. Нельзя поставить на продакшен дотМемори из инсталлера? Берем RemoteAgent, копируем на продакшен, запускаем (это экзешничек с wcf сервисом), аттачимся удаленно, см. п.1

FR>Такие варианты совсем не спасают?


Согласен с Tom. Добавлю еще несколько вариантов:
1) сервер отъел слишком много памяти, админы/поддержка/watchdog сделали дамп и перезапустили его;
2) сервер упал, автоматически сделался дамп памяти.
Re[10]: Юнит тестирование "памяти"
От: fedor.reznik  
Дата: 20.04.15 17:09
Оценка:
Здравствуйте, Tesh, Вы писали:

T>Согласен с Tom. Добавлю еще несколько вариантов:

T>1) сервер отъел слишком много памяти, админы/поддержка/watchdog сделали дамп и перезапустили его;
T>2) сервер упал, автоматически сделался дамп памяти.

Угу, спасибо!
Re[7]: Юнит тестирование "памяти"
От: Tesh США  
Дата: 20.04.15 17:18
Оценка:
Здравствуйте, fedor.reznik, Вы писали:

FR>Так вот предлагается частично автоматизировать это приемочно/нагрзочное тестрирование


Так или иначе все равно здорово, что вы этим занимаетесь.
Даже если оно не будет широко использоваться, возможно эти наработки станут ступенью на пути к чему-то еще более интересному (по аналогии с фундаментальными науками)
Re[8]: Юнит тестирование "памяти"
От: fedor.reznik  
Дата: 20.04.15 17:20
Оценка:
Здравствуйте, Tesh, Вы писали:

T>Здравствуйте, fedor.reznik, Вы писали:


FR>>Так вот предлагается частично автоматизировать это приемочно/нагрзочное тестрирование


T>Так или иначе все равно здорово, что вы этим занимаетесь.

T>Даже если оно не будет широко использоваться, возможно эти наработки станут ступенью на пути к чему-то еще более интересному (по аналогии с фундаментальными науками)

Вашими бы словами
Re[11]: Юнит тестирование "памяти"
От: Sinix  
Дата: 20.04.15 19:40
Оценка:
Здравствуйте, fedor.reznik, Вы писали:

FR>Угу, спасибо!

Ещё один юзкейз, буквально на прошлой неделе: outofmemoryexception в стороннем компоненте.

Запускаем процесс под дотмемори, воспроизводим, пытаемся сделать снапшот, облом — компонент под x86, АП почти полностью отожрано, фиаско Код ошибки в профайлере не запомнил, не до того было, если сильно надо — попробую воспроизвести. Позже из спортивного интереса прогнал триалом ants profiler — итог тот же.

VS 2013 + memory dumps — наше всё, короче.
Re[12]: Юнит тестирование "памяти"
От: fedor.reznik  
Дата: 21.04.15 11:05
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Запускаем процесс под дотмемори, воспроизводим, пытаемся сделать снапшот, облом — компонент под x86, АП почти полностью отожрано, фиаско Код ошибки в профайлере не запомнил, не до того было, если сильно надо — попробую воспроизвести. Позже из спортивного интереса прогнал триалом ants profiler — итог тот же.


Если будет время воспроизведите, пожалуйста, сразу с логами:
How to get Core logs

А потом любым удобным вам способом расшарьте логи нам. Как вариант через ftp://ftp.intellij.net/.uploads/

Заранее, спасибо.
Re[13]: Юнит тестирование "памяти"
От: Sinix  
Дата: 21.04.15 11:19
Оценка:
Здравствуйте, fedor.reznik, Вы писали:

FR>Если будет время воспроизведите, пожалуйста, сразу с логами:

Ок, постараюсь на этой неделе.
Re: Юнит тестирование "памяти"
От: Spinifex Россия https://architecture-cleaning.ru/
Дата: 22.04.15 06:27
Оценка:
Интересная вещь, иногда нужно зафиксировать результаты работ по оптимизации памяти.
Решил попробовать и набросал простейший пример (см. ниже).
Под debug он проходит, а под релизом сразу падает. Что естественно b1 и b2 — не используются в коде.
Не совсем очевидный нюанс при таком подходе: у нас появляется зависимость от конфигурации билда.

На мой взгляд было бы удобным иметь возможность получать размер не только объекта, но и все его ссылок.
Когда планируется интеграция с CI?

public class Some
{
    private int d;
}

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void TestMethod1()
    {
        var b1 = new Some();
        var b2 = new Some(); 
         
        var memoryCheckPoint1 = dotMemory.Check(
              memory =>
                   {
                        Assert.AreEqual(2, memory.GetObjects(where => where.Type.Is<Some>()).ObjectsCount, "Неверное количество объектов");
                    }
                );
            
        GC.Collect();
            
        var memoryCheckPoint2 = dotMemory.Check(
                    memory =>
                    {
                        Assert.AreEqual(2, memory.GetDifference(memoryCheckPoint1).GetSurvivedObjects().GetObjects(where => where.Type.Is<Some>()).ObjectsCount, "Неверное количество объектов");
                    }
                );
        }
    }
Re[13]: Юнит тестирование "памяти"
От: Sinix  
Дата: 22.04.15 08:26
Оценка:
Здравствуйте, fedor.reznik, Вы писали:

FR>Если будет время воспроизведите, пожалуйста, сразу с логами:


В логах ничего толком нет, воспроизвёл кодом:
    static void Main()
    {
        var l = new List<IntPtr>();
        var size = 64 * 1024 * 1024;
        for (int i = 0; i < 1024*1024; i++)
        {
            try
            {
                l.Add(Marshal.AllocCoTaskMem(size));
            }
            catch (Exception)
            {
                size /= 2;
            }
            Console.WriteLine("{0:N2} kb", Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0);

            Thread.Sleep(1000);
        }
        GC.KeepAlive(l);
        Console.WriteLine("Done.");
        Console.ReadKey();
    }


Сборка debug, x86, .net 3.5, запустил из-под standalone-профайлера, периодически снимал снапшоты. На ~1.8 гб упало с E_OUTOFMEMORY. После этого ни закрыть, ни сохранить снапшот не получается, профайлер прибивается только через диспетчер задач.
Re[14]: Юнит тестирование "памяти"
От: fedor.reznik  
Дата: 22.04.15 09:46
Оценка: +1
Здравствуйте, Sinix, Вы писали:

S>
S>    static void Main()
S>    {
S>        var l = new List<IntPtr>();
S>        var size = 64 * 1024 * 1024;
S>        for (int i = 0; i < 1024*1024; i++)
S>        {
S>            try
S>            {
S>                l.Add(Marshal.AllocCoTaskMem(size));
S>            }
S>            catch (Exception)
S>            {
S>                size /= 2;
S>            }
S>            Console.WriteLine("{0:N2} kb", Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0);

S>            Thread.Sleep(1000);
S>        }
S>        GC.KeepAlive(l);
S>        Console.WriteLine("Done.");
S>        Console.ReadKey();
S>    }
S>


S>Сборка debug, x86, .net 3.5, запустил из-под standalone-профайлера, периодически снимал снапшоты. На ~1.8 гб упало с E_OUTOFMEMORY.

Ситуация ясна. Вы отъели всю нативную память таким образом. А профайлер на стороне приложения нативный и ему стало плоховато.

S>После этого ни закрыть, ни сохранить снапшот не получается, профайлер прибивается только через диспетчер задач.


Это баг, все равно должна быть возможность корректно завершиться. Спасибо! Будем разбираться.
Re[14]: Юнит тестирование "памяти"
От: WW898 Германия  
Дата: 22.04.15 09:46
Оценка: 36 (1)
Здравствуйте, Sinix, Вы писали:

S>Здравствуйте, fedor.reznik, Вы писали:


FR>>Если будет время воспроизведите, пожалуйста, сразу с логами:


S>В логах ничего толком нет, воспроизвёл кодом:

S>
S>    static void Main()
S>    {
S>        var l = new List<IntPtr>();
S>        var size = 64 * 1024 * 1024;
S>        for (int i = 0; i < 1024*1024; i++)
S>        {
S>            try
S>            {
S>                l.Add(Marshal.AllocCoTaskMem(size));
S>            }
S>            catch (Exception)
S>            {
S>                size /= 2;
S>            }
S>            Console.WriteLine("{0:N2} kb", Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0);

S>            Thread.Sleep(1000);
S>        }
S>        GC.KeepAlive(l);
S>        Console.WriteLine("Done.");
S>        Console.ReadKey();
S>    }
S>


S>Сборка debug, x86, .net 3.5, запустил из-под standalone-профайлера, периодически снимал снапшоты. На ~1.8 гб упало с E_OUTOFMEMORY. После этого ни закрыть, ни сохранить снапшот не получается, профайлер прибивается только через диспетчер задач.


Привет, спасибо за тест. Я его погоняю у себя, чтобы отполировать работу core. С другой стороны core отработала нехватку паияти и в логах есть:

11:15:52.514 |W| CommandProcessor | OnLogAlert severity=Error hr=8007000E message='Can't allocate memory for profiler core'

Думаю дело во взаимодействии UI и core. Есть шанс починить это в грядущем релизе.
Re[2]: Юнит тестирование "памяти"
От: fedor.reznik  
Дата: 22.04.15 09:53
Оценка: 54 (1)
Здравствуйте, Spinifex, Вы писали:

S>Под debug он проходит, а под релизом сразу падает. Что естественно b1 и b2 — не используются в коде.

S>Не совсем очевидный нюанс при таком подходе: у нас появляется зависимость от конфигурации билда.

Вообще говоря, профилировать имеет смысл только Release версии. Хотя ваш пример несколько искусственный и в реальности таких засад будет меньше, но тем не менее.

S>На мой взгляд было бы удобным иметь возможность получать размер не только объекта, но и все его ссылок.

Их есть у нас!

var memoryCheckPoint1 = dotMemory.Check(
              memory =>
                   {
                        Assert.AreEqual(2, memory
                    .GetObjects(where => where.Type.Is<Some>())
                    .GetExclusivelyRetainedObjects() // получает выборку объектов удерживаемым данной выборкой
                    .ObjectsCount, "Неверное количество объектов");
                    }
                );


S>Когда планируется интеграция с CI?

Собственно она уже в разработке. Так что, видимо, в ближайших релизах. Скажем так, до конца года с вероятностью 99% Может и пораньше.

UPD: GC.Collect() можно не вызывать. Снятие снапшота (чек-пойнта), гарантирует сборку мусора.
Отредактировано 22.04.2015 9:58 fedor.reznik . Предыдущая версия .
Re[2]: Юнит тестирование "памяти"
От: Ed.ward Россия  
Дата: 22.04.15 11:28
Оценка:
Здравствуйте, Spinifex, Вы писали:

S>Интересная вещь, иногда нужно зафиксировать результаты работ по оптимизации памяти.

S>Решил попробовать и набросал простейший пример (см. ниже).
S>Под debug он проходит, а под релизом сразу падает. Что естественно b1 и b2 — не используются в коде.
S>Не совсем очевидный нюанс при таком подходе: у нас появляется зависимость от конфигурации билда.

Здесь вы тестируете тест, отсюда и проблема. Если вы напишете простейшую инкапсулированную логику и протестируете её, проблема исчезнет.
Оптимизации в Release конфигурации действительно могут освободить пременную раньше выхода за зону видимости, но поймать это тестом без многопоточности нельзя.

Ed.ward
Re[3]: Юнит тестирование "памяти"
От: Spinifex Россия https://architecture-cleaning.ru/
Дата: 23.04.15 06:00
Оценка: +1
Здравствуйте, fedor.reznik, Вы писали:

S>>Под debug он проходит, а под релизом сразу падает. Что естественно b1 и b2 — не используются в коде.

S>>Не совсем очевидный нюанс при таком подходе: у нас появляется зависимость от конфигурации билда.

FR>Вообще говоря, профилировать имеет смысл только Release версии. Хотя ваш пример несколько искусственный и в реальности таких засад будет меньше, но тем не менее.


Возможно два варианта:
1. Мы пишем юнит тесты на каждый класс.
2. Мы пишем что-то вроде нагрузочных тестов на сценарии и смотрим чтобы в этом сценарии память расходовалась в приемлемых объемах.

Плюсы первого подхода:

а) можно быстро понять что конкретно сломалось; б) быстрые.
Минусы первого подхода:
а) зависят от внутреннего дизайна кода — в случае рефакторинга нужно будем менять кучу тестов. б) банально больше строк кода с тестами в сравнении со вторым подходом.

Плюсы второго подхода:

а) т.к. привязаны к сценариям, любой член команды может понять что сломалось (тестер, менеджер и т.п.; особенно если это реализовано с помощью Specflow). Все понимают, что допустим в сценарии "Создание резервной копии структуры библиотеки" в этой версии софта расходуется память; б) кода самих тестов заметно меньше; в) нет зависимости от внутренней организации кода — нам абсолютно без разницы какие классы и с кем взаимодействуют, где и в каком классе теперь хранятся данные, главное чтобы сценарий в целом не расходовал память. Т.е. в случае рефакторинга тесты не переписываются; г)
Минусы второго подхода:
а) Разработчику нужно отлаживаться, чтобы понять что именно привело к падению теста; б) медленные.

Вы сейчас реализовали поддержку первого подхода. Лично мне кажется, что тестирование (а точнее, наверное, профилирование) памяти лучше ложится на второй подход. Причем мне видится так: ставим через инсталятор на виртуальную машину серверную часть, аналогично клиентскую часть. Прогоняем через CodedUI сценарий и смотрим что с памятью. Вот если бы dotMemory выступал как сервис: в какой-то момент указываешь процесс, в какой-то момент получаешь результат.

Разве Вам (JetBrains) не проще реализовать такой функционал, чем делать библиотеку для Unit тестирования? ИМХО такой подход найдет не мало своих сторонников.
Отредактировано 23.04.2015 6:01 Nikita Lyapin . Предыдущая версия .
Re[4]: Юнит тестирование "памяти"
От: fedor.reznik  
Дата: 23.04.15 09:38
Оценка: 17 (1)
Здравствуйте, Spinifex, Вы писали:

Про сценарные vs юнит тесты, я поскипал, потому что согласен. Нужны и те и те, вон в соседней ветке эта тема как раз бурлит)

S>Вы сейчас реализовали поддержку первого подхода.

Не согласен!
Давайте я покажу как выглядит сценарный тест dotMemory:

    [Test]
    public void FirstSnapshotAllocationsTest()
    {
      using(var lt = new TransientLifetime())
      {
        var executable = ShellInstance.BuildExecutable<SnapshotsForSimpleAllocations>(lt); // компилируем код
        var allocationsTree = TestedDotMemory.StartProfiling(ProfilerConfigurator.ProfileByApi(executable), lt) // запускаем реальную профиляцию с неким набором параметров
          .AwaitAnalisys()
          .AwaitProfilingSession()
          .AwaitForSnapshots(2) // получили снапшоты
          .First() 
          .OpenAllObjects() // открыли все объекты
          .OpenObjectSetByType() // открыли группировку по типам
          .RunAction(presenter => presenter.AwaiForObjectsByType())
          .OpenSubset(node => node.Kind == ModelEntityKind.OfClass
                              && (node.DisplayName.ToString().Contains(typeof (SnapshotsForSimpleAllocations.MegaTestObject).Name)
                                  || node.DisplayName.ToString().Contains(typeof (SnapshotsForSimpleAllocations.GigaTestObject<>).Name.TrimEnd('`', '1')))) // открыли подсет по определенному условию
          .OpenAllocationsTree() // открыли группировку по аллокациям
          .AwaitAllocationsTree(); // дождались пока аллокации посчитаются

    // ассертим что дм все правильно посчитал
        Assert.That(
          allocationsTree.Sum(_ => _.Statistics.SubTreeAllocatedObjectsCount),
          Is.EqualTo(SnapshotsForSimpleAllocations.GigaTestObjectsInitialCount + SnapshotsForSimpleAllocations.MegaTestObjectsInitialCount));
      }
    }


При этом TestedDotMemory — это не какой-то магический класс, а просто набор статических методов и экстеншенов над интерфейсом VM для выполнения типовых операций.
То есть в этом тесте тестируется один в один тот код, с которым работает пользователь.
Единственное, что не тестируется, так это UI биндинги и прочие лайауты "кнопочек", но это уже и тестер сможет посмотреть.
Да местами нам пришлось пройти через "боль и страдания" и упороться по MVVM, но оно того стоило Ибо нам теперь и сценарные тесты писать легко и перформанс/мемори тесты тоже сюда ложатся на ура.


S>Лично мне кажется, что тестирование (а точнее, наверное, профилирование) памяти лучше ложится на второй подход.

Согласен, но тут вопрос как второй подход имплементить, если в виде "обычных" тестов (см. выше), то все в шоколаде.

S>Причем мне видится так: ставим через инсталятор на виртуальную машину серверную часть, аналогично клиентскую часть. Прогоняем через CodedUI сценарий и смотрим что с памятью. Вот если бы dotMemory выступал как сервис: в какой-то момент указываешь процесс, в какой-то момент получаешь результат.

S>Разве Вам (JetBrains) не проще реализовать такой функционал, чем делать библиотеку для Unit тестирования? ИМХО такой подход найдет не мало своих сторонников.

JetBrains — это не проще, потому что а) нам это не очень нужно, б) это не меньший, а, имхо, гораздо больший геммор по созданию апи сервиса на все случаи жизни.
Кроме того, такой продукт, скорее всего, будет уже платным, что не всем понравится(
В принципе, Вы уже сейчас можете снимать снапшоты со своего кода через Profiling Api, хоть через CodedUI, хоть через как, при этом клиентом выступает сам дотМемори.
Удаленную профиляцию мы тоже поддерживаем.
Чего Вам не хватает, так это консольного репортинга из дм, для того, чтобы автоматически парсить результаты. Возможно мы его реализуем, но это опять же вопрос времени и приоритетов.
Re[5]: Юнит тестирование "памяти"
От: Sinix  
Дата: 23.04.15 10:32
Оценка: 6 (1)
Здравствуйте, fedor.reznik, Вы писали:

FR>Давайте я покажу как выглядит сценарный тест dotMemory:


Такой вопрос: что в тесте — инфраструктурный код от DotMemoryUnit, а что — собственно тест?
Если весь код кроме Assert.That() — это инфраструктура, то выглядит страшновато.

Есть ещё вариант 2: я тормоз, код — обычный сценарный тест и тут вообще речь не про тестирование с использованием DotMemoryUnit

Если со вторым вариантом угадал — как в DotMemoryUnit будет выглядеть типовой тест для сферического кода в вакууме?
В моём представлении код должен выглядеть примерно так (псевдокод):
var memoryContract = Memory
  .WillNotLeak(threshold: 1kb)
  .NoLohInstances()
  .MaxAllocates(10mb)
  .WarnOnMidlifeCrisis()

using (new AssertionScope(memoryContract))
{
  SomeUseCase();
}


Т.е. отдельно прописываем гарантии для кода (не течём, не замусориваем LOH, дельта по памяти — не больше 10 МБ, код не становится причиной Mid-life crisis), отдельно — запускаем сценарий.

Если у вас будет другой способ — делитесь, интересно
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.