Да, да. На хабре сидят представители очень многих контент-провайдеров и агрегаторов. И для большинства из них такой «вирус» — повод «расследования» для собственной «службы безопастности», пока не пришло гневное письмо от операторов. Во-первых, залочат вымогателя, во-вторых, опубликуют открытый код, который нужно ввести без СМС ;-)…
Вот как раз в случае с виртуальной машиной Private Bytes очень важно. Виртуальная машина работает не с памятю, а кучей, размер которой вы получили при помощи GC.GetTotalMemory. Разница же между Private Bytes и GC.GetTotalMemory и есть затраты виртуальной машины. Вас не смутило то, что при МТ я performance.RawValue получал в залоченной области, иначе бы могло быть закрыто несколько потоков и соответственно освобождена память мгновенно, на уровне менеджера памяти защищенного режима самой ОС.
О, я понял о чем вы. У нас разное понятие производительности. Вы оцениваете затраты физического (астрономического) времени, я же оцениваю затраты в «астрономических» тактах процессора. Т.е. на вашей машинке бы «астрономические» паразитные затраты были бы в 2 раза меньше, т.к. у вас 2 3хГц процессора(ядра). Здесь я наверное допустил самую большую ошибку. Мне стоило писать сразу в тактах процессора… Хорошая мысля как говориться…
Смотрите. Есть у нас 1200 запросов и 4 обработчика в ThreadPool. Легкой операцией деления мы получаем по 300 запросов на поток. Увеличим поток запросов в 4 раза и получаем 4 засинхронизированных однопоточных обработчика, рассмотренных в первой части поста. Единственное что мы получим — полная загрузка всех ядер и процессоров системы при минимальных затратах памяти…
Именно. При этом не всегда алгоритм распараллеливания обработчиков может привести к увеличению производительности, т.к. простои из-за паразитного времени на выделение потоков бывает больше, чем сама обработка потока.
ThreadPool это некий компромис. Он хорош тогда когда потоки в основном живут в sleep. Когда же их основная задача — обработать запрос и умереть, то ThreadPool можно рассматривать как несколько однопоточных обработчиков, синхронизированных между собой общей очередью. При этом мы выигрываем в производительности и несильно проигрываем в памяти. Но от основной проблемы однопоточного обработчика, зависимости общего времени основных потоков от времени выполнения всех запросов, мы не избавляемся.
явное указание максимального размера стека для потока никак на результате не отразилось
Все дело в том, что вы смотрите на изменение размера кучи, а не на изменение объема Private Bytes текущего процесса. время работы в MT не зависит от количества запросов при num_of_threads >> mockSpeed. А вот тут поподробнее, у меня «паразитные нагрузки» вашего кода — огромные…
Кстати забыл заострить внимание на одном-единственном комментарии в программах. Хоть мы и выделили всего 64Кб памяти, поток сожрал 256Кб. Я где-то читал что 256Кб минимальный возможный объем памяти выделяемый под стек в Vista. В .Net такая же фигня твориться и на XP :)
1. Спасибо конечно же стек потоков. Подправил. Стек потоку необходим для передачи параметров в методы, сохранение состояний объектов для возврата из других методов, их виртуальных таблиц.
2. Как я и сделал чтобы получить общее время, с так называемыми паразитными нагрузками, которые расходуются на запуск-завершение потоков, синхронизацию между ними.
3. Как вы видите при однопотоковом формируется формула (mockSpeed+1)*N, где +1 можно отнести к паразитным нагрузкам, тогда же как в многопоточном эта формула 0.5*N+(mockSpeed+1.5)*N или (mockSpeed+2)*N, где уже +2 — значение паразитных нагрузок.
О, я понял о чем вы. У нас разное понятие производительности. Вы оцениваете затраты физического (астрономического) времени, я же оцениваю затраты в «астрономических» тактах процессора. Т.е. на вашей машинке бы «астрономические» паразитные затраты были бы в 2 раза меньше, т.к. у вас 2 3хГц процессора(ядра). Здесь я наверное допустил самую большую ошибку. Мне стоило писать сразу в тактах процессора… Хорошая мысля как говориться…
Все дело в том, что вы смотрите на изменение размера кучи, а не на изменение объема Private Bytes текущего процесса.
время работы в MT не зависит от количества запросов при num_of_threads >> mockSpeed. А вот тут поподробнее, у меня «паразитные нагрузки» вашего кода — огромные…
2. Как я и сделал чтобы получить общее время, с так называемыми паразитными нагрузками, которые расходуются на запуск-завершение потоков, синхронизацию между ними.
3. Как вы видите при однопотоковом формируется формула (mockSpeed+1)*N, где +1 можно отнести к паразитным нагрузкам, тогда же как в многопоточном эта формула 0.5*N+(mockSpeed+1.5)*N или (mockSpeed+2)*N, где уже +2 — значение паразитных нагрузок.