Здравствуйте, prVovik, Вы писали:
V>А можно реальный жизненный пример, в которм применение синглтона оправдано и дает _преимущества_ перед другими решениями, а не равнозначно с ними. С примерами, где синглтон имеет недостатки у меня проблем нет. А вот с преимуществами — что-то ничего в голову не лезет
Здравствуйте, Sergei Soloviev, Вы писали: SS>А можно в двух словах, что это такое, читал Wikipedia, не очень хорошо понял.
Это всё о том, где одни объекты берут другие объекты.
В принципе, когда работает метод какого-то объекта, у него есть доступ вот к чему:
1. К объектам, которые ему передали в параметрах
2. К объектам, ссылки на которые сохранены в полях текущего объекта
3. К глобальным переменным
4. К статическим методам классов (включая конструкторы, т.е. к вновь созданным объектам)
Способ 1 предъявляет меньше всего требований к окружению объекта, но он неудобен тем, что части "окружающей вселенной" приходится протаскивать сквозь весь стек.
IoC — это про замену способов 3 и 4 на 2.
Вот пример:
public int Add(int a, int b)
{
System.Console.WriteLine("adding {0} and {1}", a, b);
return a + b;
}
Здесь объект сам решил найти себе консоль и вывести текст в нее (используя статический метод класса Console).
IoC меняет место, где принимается решение о том, какой поток вывода использовать:
public class MyClass
{
public TextWriter LogOutput
{
set { _logOutput = value;}
}
public int Add(int a, int b)
{
_logOutput.WriteLine("adding {0} and {1}", a, b);
return a + b;
}
}
Здесь вызывающий код должен заранее позаботиться о том, чтобы выполнить myClass.LogOutput = System.Console.Out.
Это разумный компромисс между передачей System.Console.Out при каждом вызове Add и изначальным вариантом.
Если правильно организовать взаимодействие между классами, то непосредственный клиент класса MyClass даже не обязан знать о том, что нужно выбирать какой-то логгер. (Как это и было в начальном варианте). Экземпляр MyClass мог быть "спущен сверху" этому клиенту уже настроенным.
То есть начинаем мы примерно так:
public class Aggregate
{
public int CountSum(IEnumerable<int> input)
{
int sum=0;
MyClass adder = new MyClass(); // сами конструируем себе объектforeach(int item in input)
sum = adder.Add(sum, item);
return sum;
}
}
а заканчиваем примерно так:
public class Aggregate
{
private MyClass _adder;
public MyClass Adder { set { _adder = value;}}
public int CountSum(IEnumerable<int> input)
{
int sum=0;
foreach(int item in input)
sum = _adder.Add(sum, item);
return sum;
}
}
...
public static void Main()
{
int[] a = new int[] {1, 2, 3, 4, 5,};
MyClass adder = new MyClass();
adder.LogOutput = System.Console.Out;
Aggregate agg = new Aggregate();
agg.Adder = adder;
int sum = agg.CountSum(a);
}
Здесь немножко больше обязанностей возлагается на Main, т.к. ему нужно обеспечить всех информацией о том, кто кого должен использовать, но зато эти зависимости собраны в одном месте, и ими легко управлять. Нам не нужно выискивать по коду все обращения к консоли, чтобы научить программу логгировать в файл — достаточно поменять одну строку.
Мы можем заменить алгоритм "сложения" без переписывания класса Aggregate.
Потому паттерн и называется "Inversion of Control" — право принятия решений переносится с "исполнителя" на "командира".
В сильно заархитектуренных средах основные строительные классы никогда не обращаются к чужим статик методам и полям, а работают исключительно со своими полями. За инициализацией следит среда, зачастую при помощи файлов конфигурации, так что можно добиться произвольно разнообразного поведения без пересборки программы.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[8]: класс Singleton - разобрался, но где в "жизни" примен
Здравствуйте, minorlogic, Вы писали: M>Очевидно что для эфективности такой объект должен жить в одном экземпляре. Остальное ты сам додумал.
Гм. А можно развернуть это "очевидное" доказательство?
У меня лично ровно обратное ощущение: одним пулом потоков можно пользоваться ровно до тех пор, пока недостаточная эффективность не приведет к необходимости использовать больше.
Подробнее:
основным параметром пула потоков является предел количества одновременно выданных потоков. Если его необоснованно завышать, то throughput будет снижаться из-за расходов на переключение контекста. Грубо говоря, выдавать "еще один" поток из пула можно тогда, когда часть CPU ресурсов простаивает. В противном случае, лучше подождать освобождения занятого потока. К сожалению, известные мне реализации не способны достаточно эффективно отслеживать реальную нагрузку, поэтому пулы реализованы в предположении однотипности потоков, а также в предположении, что администратор в состоянии сам оценить разумное количество потоков для одновременного исполнения.
Как только предположение об одинаковости потоков нарушается, начинаются проблемы. Пример: веб приложение, в котором одна страница генерится быстро, а другая обращается к удаленному серверу. Обращения к странице №1 обрабатываются нашим CPU. В среднем, поток, обрабатывающий запрос к странице №1, занимает 25% CPU. Это означает, что не имеет смысла разрешать запускать более четырех потоков одновременно.
Поток, обрабатывающий страницу №2, большую часть времени спит. В среднем, он занимает 1% СPU. Это означает, что лимит в 4 потока загрузит нашу машину примерно на 4%, остальные запросы будут ждать в очереди. Очевидно, что throughput будет примерно в 25 раз ниже, чем мог бы быть. Лимит в 100 потоков приведет к тому, что одновременно будут обслуживаться слишком много запросов к странице 1, увеличивая response time и опять же снижая throughput.
В результате, очевидно, что для достижения максимальной эффективности в данном случае придется завести два пула потоков, с совершенно различными лимитами. Что, кстати, описано в соответствующей статье от Microsoft.
В связи с вышеизложенным, мне никак не понятно, каким боком требования эффективности могут привести к предложенному тобой ограничению на количество пулов потоков.
З.Ы. В качестве оффтопа, можно пообсуждать возможные реализации пулов ресурсов, способные избегать описанной проблемы даже при единственном экземпляре пула в системе.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: класс Singleton - разобрался, но где в "жизни" примен
Очевидно что 10 пулов с лимитом в 4 потока будут больше простаивать чем 1 пул с лимитом 40. Я не утверждаю что такая ситуация присутствует всегда , вы сами привели яркие примеры не вписывающиеся в эту картину.
Если пул потоков кажется сомнительным кандидатом на сингелтон то могу предложить планировщик задач (алгоритмически вероятно лучше иметь один планировщик).
З.Ы. Можно в имплементации запланировать различные сценарии и поведение с учетом приоритетов и т.п.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[10]: класс Singleton - разобрался, но где в "жизни" приме
Здравствуйте, minorlogic, Вы писали:
M>Очевидно что 10 пулов с лимитом в 4 потока будут больше простаивать чем 1 пул с лимитом 40.
1. Очевидно, что это утверждение не имеет никакого отношения к решению, делать ли пул синглтоном. Верно?
2. Предыдущее "очевидное" умозаключение оказалось несовместимым с действительностью. Почему ты думаешь, что это утверждение ждет лучшая судьба?
3. В связи с 1 и 2, предлагаю более тщательно подумать над своими заявлениями. Очевидно, что одно осторожное и верное утверждение лучше, чем десять категоричных и неверных, не так ли?
M>Я не утверждаю что такая ситуация присутствует всегда , вы сами привели яркие примеры не вписывающиеся в эту картину.
В какую картину? Синглтон, простите, это как скрижали — высек в камне и живи с ним. Выковырять синглтон из развитого приложения крайне тяжело. Если он подходит лишь для узкого набора частных случаев применения нашей программы/фреймворка/библиотеки, то может быть сразу реализовать общий случай с произвольным количеством пулов? Ибо сузить его на один экземпляр, если это удобно в данном случае, куда как проще, чем провести обратную операцию. M>Если пул потоков кажется сомнительным кандидатом на сингелтон то могу предложить планировщик задач (алгоритмически вероятно лучше иметь один планировщик).
Слова "вероятно" здесь, наверное, не вполне уместны. Я как бы ожидаю бесспорности от кандидата в синглтоны. Пул потоков, в каком-то смысле, и есть планировщик задач. Тот планировщик, который в операционке, делает, в общем-то, примерно то же, только на другом уровне, и имеет возможность динамически отбирать ресурсы у задачи до ее окончания. M>З.Ы. Можно в имплементации запланировать различные сценарии и поведение с учетом приоритетов и т.п.
Можно. Но делать такие заявления лучше с осторожностью.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[11]: класс Singleton - разобрался, но где в "жизни" приме
Вы неверно воспринимаете мои высказывания . В треде просили привести примеры объектов которые могли бы быть оправданными сингелтонами, я это и пытаюсь сделать.
Если вы думаете что я рекомендую делать пул потоков или еще ченить через сингелтон , то это не так. Я не помню случая когда бы мне необходим был сингелтон. Его использование я считаю или пробелом проектирования или банальной нехваткой опыта и попыткой делать код из книги.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[10]: класс Singleton - разобрался, но где в "жизни" приме
Здравствуйте, minorlogic, Вы писали:
M>Очевидно что 10 пулов с лимитом в 4 потока будут больше простаивать чем 1 пул с лимитом 40.
Очевидно что поток который простаивает не ест ресурсов. Кроме адресного пространства. А если учесть что 64 бита становится обычным делом... Да и 32х бит тоже хватает на очень большое колличество потоков...
M>Я не утверждаю что такая ситуация присутствует всегда , вы сами привели яркие примеры не вписывающиеся в эту картину.
Я тебе могу расказать как можно задедлочится на пуле... но ты почемуто считаешь что это невозможно
M>Если пул потоков кажется сомнительным кандидатом на сингелтон
Он не просто сомнительный.
Это вобще ярчайший пример того что ни в коем случае нельзя делать синглетоном.
Ибо он даст тебе в лоб сразу, а не при поддержке.
Причем не только и не столько тормозами сколько дедлоками.
Хотя производительность тоже важна. Грамотная настройка пулов потоков может поднять производительность системы в десятки, а то и сотни раз плюс обеспечить реактивность (медленные запросы не тормозят быстрые). И все это без переписывания кода. Исключительно правкой конфигов.
А если мы имеем дело с распределенкой то неправильно настроеные пулы могут приводить к распределенным дедлокам (это когда 2 или болие машин лочатся друг на друга). Причем тут даже циклы (машина А спрашивает машину Б, машина Б спрашивает машину А) не нужны.
M>то могу предложить планировщик задач (алгоритмически вероятно лучше иметь один планировщик).
Гм. Вот у меня перед глазами сервачек с сотнями тысяч потоков уровня приложения...
Там есть шедуллер...
Я думаю ты уже догадался что он не синглетон...
M>З.Ы. Можно в имплементации запланировать различные сценарии и поведение с учетом приоритетов и т.п.
Чем слово реализация не устраивает?
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[12]: класс Singleton - разобрался, но где в "жизни" приме
Здравствуйте, minorlogic, Вы писали:
M>Вы неверно воспринимаете мои высказывания . В треде просили привести примеры объектов которые могли бы быть оправданными сингелтонами, я это и пытаюсь сделать.
Это понятно.
Мне непонятно обоснование ваших примеров. Угадывать за ними какие-то философские корни я вообще даже не собираюсь.
M>Если вы думаете что я рекомендую делать пул потоков или еще ченить через сингелтон , то это не так.
Странно. Из ваших сообщений следует ровно это. Рассмотрим, к примеру, вот такое сообщение:
Например пул потоков. Очевидно что для эфективности такой объект должен жить в одном экземпляре
В нем сделано сразу два неправильных утверждения. Поясню еще раз:
1. "для эфективности такой объект должен жить в одном экземпляре" — неправда; для максимальной эффективности нужно отдельно пулить задачи с разными профилями активности
2. "Очевидно что" — неправда; эффективность настолько нетривиально зависит от алгоритмов, что очевидных зависимостей практически нет.
Я не понимаю, как при их помощи заведомо неправильных утверждений можно обосновывать применение паттерна Синглтон.
M> Я не помню случая когда бы мне необходим был сингелтон. Его использование я считаю или пробелом проектирования или банальной нехваткой опыта и попыткой делать код из книги.
Тогда вообще непонятно, зачем ты пытаешься защищать синглтон. Или это такой тонкий сарказм — попытка предложить заведомо неверные применения синглтона чтобы его дискредитировать?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[13]: класс Singleton - разобрался, но где в "жизни" приме
Например пул потоков. Очевидно что для эфективности такой объект должен жить в одном экземпляре
S>В нем сделано сразу два неправильных утверждения. Поясню еще раз: S>1. "для эфективности такой объект должен жить в одном экземпляре" — неправда; для максимальной эффективности нужно отдельно пулить задачи с разными профилями активности
Вы рассматриваете часный случай , когда пользователь знает о "профилями активности задачи". Если такая информация есть, то конечно ее можно использовать для улучшения показателей работы пула/пулов. Попробуйте посмотреть на задачу с точки зрения когда про таски для пула вы ничего не знаете одинаково.
S>2. "Очевидно что" — неправда; эффективность настолько нетривиально зависит от алгоритмов, что очевидных зависимостей практически нет.
Если не очевидно предлагаю провести эксперимент с 10 пулами по 4 потока и одним пулом с 40 потоками. Задачи запускаемые на пулах оставте в тесте одинаковыми.
S>Я не понимаю, как при их помощи заведомо неправильных утверждений можно обосновывать применение паттерна Синглтон.
Повторяю в последний раз , я НИГДЕ не обосновывал "применение паттерна Синглтон", это ваша фантазия.
M>> Я не помню случая когда бы мне необходим был сингелтон. Его использование я считаю или пробелом проектирования или банальной нехваткой опыта и попыткой делать код из книги. S>Тогда вообще непонятно, зачем ты пытаешься защищать синглтон. Или это такой тонкий сарказм — попытка предложить заведомо неверные применения синглтона чтобы его дискредитировать?
См. выше, и не фантазируйте.
Ищу работу, 3D, SLAM, computer graphics/vision.
Re[12]: класс Singleton - разобрался, но где в "жизни" приме
Здравствуйте, minorlogic, Вы писали:
M>В треде просили привести примеры объектов которые могли бы быть оправданными сингелтонами, я это и пытаюсь сделать.
Вообще-то я просил привести пример, когда синглтон имеет _преимущества_ перед другими решениями (например, перед IoC). В примере с пулом потоков я никаких преимуществ кроме возможного в будущем гемороя не увидел.
M>Если вы думаете что я рекомендую делать пул потоков или еще ченить через сингелтон , то это не так. Я не помню случая когда бы мне необходим был сингелтон. Его использование я считаю или пробелом проектирования или банальной нехваткой опыта и попыткой делать код из книги.
О том и речь.
лэт ми спик фром май харт
Re[6]: класс Singleton - разобрался, но где в "жизни" примен
Здравствуйте, minorlogic, Вы писали:
M>Здравствуйте, prVovik, Вы писали:
V>>Жить в одном экземпляре и синглтон — это не одно и тоже.
M>начит мы говорим о разных вещах.
Ну если ты под синглтоном понимаешь все что угодно, что может предоставить объект, существующий в единственном экземпляре, то да, мы говорим о разных вещах. Только учти, что под твое определение синглтона может попасть тот же IoC и кучи других разных решений.
лэт ми спик фром май харт
Re[3]: класс Singleton - разобрался, но где в "жизни" примен
Здравствуйте, Аноним, Вы писали:
А>А вот для каких жизненных ситуаций может быть использован Singleton ?
имхо, в одном приложении достаточно одного синглтона, которым является сама аппликация (App класс). случаи, когда требуются еще синглтоны встречаются относительно редко.
проклятый антисутенерский закон
Re[11]: класс Singleton - разобрался, но где в "жизни" приме
Здравствуйте, WolfHound, Вы писали:
M>>Я не утверждаю что такая ситуация присутствует всегда , вы сами привели яркие примеры не вписывающиеся в эту картину. WH>Я тебе могу расказать как можно задедлочится на пуле... но ты почемуто считаешь что это невозможно
Мне расскажи.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
HgLab: Mercurial Server and Repository Management for Windows
Re[12]: класс Singleton - разобрался, но где в "жизни" приме
Здравствуйте, Нахлобуч, Вы писали:
WH>>Я тебе могу расказать как можно задедлочится на пуле... но ты почемуто считаешь что это невозможно Н>Мне расскажи.
1)Клиент спрашивает машину А. Машина А спрашивает машину Б. Машина Б спрашивает машину А. Если на машине А один пул потоков и клиенты много спрашивают то будет дедлок.
2)Есть две машины. Запросы от клиентов обрабатываются обе машины. Обычно справляются сами но иногда приходится спрашивать соседа. Если на каждой машине один пул то при большом колличестве запросов будет дедлок.
...
Обе описанные проблемы решаются отдельным пулом для внутренних запросов.
В реальной жизни может быть нужно больше чем два пула. Но там уже не только разруливание дедлоков но и обеспечение реактивности засчет разнесения медленных и быстрых запросов в разные пулы и ограничение запросов упирающихся в процессор выставлением колличества потоков в колличество процессоров — 1 итп...
Это не считая баналностей типа: Задача которая выполняется в пуле хочет создать несколько асинхронных подзадач и дождаться от них ответа (например спросить несколько соседних серверов).
Очевидно если задачи и поздадачи засунуть в один пул то рано или поздно будет дедлок.
... << RSDN@Home 1.2.0 alpha rev. 673>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: класс Singleton - разобрался, но где в "жизни" применить
Здравствуйте, dshe, Вы писали:
D>Избавление от singleton'а, конечно, не относится к классу Неразрешимых проблем. Однако, это может стать трудноразрешимой проблемой. По коду может быть разбросаны сотни ThreadPool.getInstance(), которые придется поменять.
Отрефакторить единообразный вызов "ThreadPool.getInstance()" даже в сотнях отдельных мест способен даже простейший текстовый редактор, умеющий делать замену по всем файлам заданного множества. Задача расширения одного синглтона до "массива синглтонов" вообще подозрительно усложнена: если в getInstance() добавить параметр — индекс или id синглтона в пуле — это проблема? Старые вызовы можно переписать как getInstance(0) — или же вынести 0 в параметр по умолчанию.
Всегда можно придумать "как нельзя сделать" — только лично я не понимаю зачем заниматься такими придумками заниматься, вместо придумок "как можно сделать".
LCR>>Синглтон — это способ вынести ограничение "один и только один объект" (что часто пересекается с ограничением "сделать инициализацию один и только один раз в самом начале") в библиотечный код.
D>... Кстати, код, в котором активно используются сингтоны, юниттестировать обычно весьма и весьма сложно (из-за того, что приходися извращаться для того, чтобы заменить реализацию синглтона).
Тут я вообще не понял: а как тогда "юниттестировать" код, в котором активно используется любой другой объект? Ну вот даже упомянутый CString — он, конечно, не синглтон, но ведь везде используется — как такой код тестировать предполагается?
Имхо, вы ищете кошку там, где ее нет.
Голь на выдумку хитра, однако...
Re[13]: класс Singleton - разобрался, но где в "жизни" приме
V>Вообще-то я просил привести пример, когда синглтон имеет _преимущества_ перед другими решениями (например, перед IoC). В примере с пулом потоков я никаких преимуществ кроме возможного в будущем гемороя не увидел.
В случае контекста — кто-то должен все время задавать этот самый контекст, каждый раз создавая его инстанс. В случае, если инстанс задается не каждый раз, а статичен — это фактически синглтон.
Re[13]: класс Singleton - разобрался, но где в "жизни" приме
WH>Обе описанные проблемы решаются отдельным пулом для внутренних запросов.
А в чем сложность создать у класса-синглтона Pool 2 метода для получения этих 2-х разных пулов? Вопрос ведь в том, нужен ли нам экземпляр класса Pool или нет. В данном случае, вроде бы, не нужен.