Потоки, net, потеря производительности
От: inevity  
Дата: 11.02.15 07:59
Оценка: :)
Здравствуйте, друзья!

Заранее прощу прощения! Я сам тракторист, но черт меня дернул заняться программированием(еще и на паскале). Опишу ситуацию по мере сил.
Но надеюсь опытные спецы без особого труда подскажут хотя бы где искать проблему.

Проблема:
Сделал программу с потоками, но при увеличении потоков польза от них падает неописуемо:
1 поток = 4% (загрузки сервера с 32 процессорами)
5 потоков — 12%
10 потоков — 15%
20 потоков — 18%
30 потоков — 18%
Предельная производительность всего в ТРИ раза больше(при 5ти потоках — дальше ухудшение), чем при одном потоке.

Исходные данные:
Программа в общем виде (схематично)
const
  ThreadCount=10;
type
  WorkClass = class
    //туча кода
  end;

var
  WorkObjects: List<WorkClass>;
  WorkObject: WorkClass;
  ThreadObjects: List<Thread>;
  ThreadObject: Thread;
  
procedure ThreadWork(WorkObject: WorkClass);
begin
  //код, суть которого WorkObject.DoWork();
end;

begin
  WorkObjects:=new List<WorkClass>;
  ThreadObjects:=new List<Thread>;

  for i:=1 to ThreadCount do
  begin
    WorkObject:=new WorkClass; WorkObjects.Add(WorkObject);
    ThreadObject:=new Thread(ThreadWork); ThreadObjects.Add(ThreadObject);
    ThreadObject.Start(WorkObject);
  end;

  //После завершения потоков обрабатываем/суммируем результаты полученных данных из объектов в списке WorkObjects
end.

Комментарий.
Класс делал так, чтобы никаких общих данных не было, т.е. в поток попадает уникальный экземпляр класса (WorkObject)
Если создаю 30 потоков — программа не увеличивается в памяти в размерах, как будто бы использует общий код(не знаю как классы располагаются в памяти и тд)
Т.е. казалось бы ничто не должно было предвещать беды, а в результата — просто катастрофа.
(есть исходный код, но он на pascal abc (pascalabc.net) — фейспалм)

Вопросы:
Не подскажите, в чем может быть проблема столь жестокой потери производительности, при отсутствии общих данных (все запихал в класс) и индивидуальном экземпляре класса для каждого потока?
Почему нет увеличения размера программы в оперативной памяти соответственно количеству потоков?



13.02.15 16:38: (это не Delphi, а PascalABC.Net) — Кодт
Отредактировано 13.02.2015 13:35 Кодт . Предыдущая версия .
Re: Потоки, net, потеря производительности
От: fmiracle  
Дата: 11.02.15 08:30
Оценка:
Здравствуйте, inevity, Вы писали:

I>Не подскажите, в чем может быть проблема столь жестокой потери производительности, при отсутствии общих данных (все запихал в класс) и индивидуальном экземпляре класса для каждого потока?


Потери производительности же вроед нет? Есть ненарастание производительности. Это чуть иное.
Тут вопрос в том, что происходит в DoWork. Это процессорно-ориентирвоанная операция? Если. например, это операция ввода-ввода (общение с диском или с сетью), то вполне может быть так, что на 10 потоках достигается максимальо допустимая загрузка этого самого диска, сетевого адаптера или внешней БД и потоки начинают постоянно ждать его освобождения. В таком случае, дальнейшее увеличение количества потоков выигрыша не дает. И загрузка процессора не растет.

I>Почему нет увеличения размера программы в оперативной памяти соответственно количеству потоков?


Оно есть, просто незаметно. Расходы памяти на сам поток достаточно небольшие, и малозаметны на фоне общих расходов памяти приложения. А сколько там метод, работающий в потоке будет потреблять оперативки — это опять же зависит от коад метода.
Плюс в .net память под работу GC выделяется блоками с запасом. Потому у приложения обычно есть некий запас памяти, который уже взят у системы, но еще не используется.
Re[2]: Потоки, net, потеря производительности
От: inevity  
Дата: 11.02.15 09:29
Оценка: :)
Здравствуйте, fmiracle, Вы писали:

F>Потери производительности же вроед нет? Есть ненарастание производительности. Это чуть иное.


До 5 потоков есть падение нарастания, после 5 потоков (6 и более) идет даже падение общей производительности! (суммарное количество обработанных данных за единицу времени становится меньше)
Как пример, если я запускаю 20 программ(а не 20 потоков), то сервер грузится ожидаемо (75-80% примерно)

F>Тут вопрос в том, что происходит в DoWork. Это процессорно-ориентирвоанная операция? Если. например, это операция ввода-ввода (общение с диском или с сетью), то вполне может быть так, что на 10 потоках достигается максимальо допустимая загрузка этого самого диска, сетевого адаптера или внешней БД и потоки начинают постоянно ждать его освобождения. В таком случае, дальнейшее увеличение количества потоков выигрыша не дает. И загрузка процессора не растет.


В DoWork Идет генерация чисел на основе экземпляра класса random (отдельный экземпляр на экземпляр рабочего класса), числа записываются в соответствующие объекты(создаются) разных логических типов.
Т.е. задача DoWork — нагенерировать данные(на данные накладываются различные фильтры).
Результат генерации — созданные объекты: создается 1000 объектов(объекты=экземпляры классов хранятся в списках LIST), затем данные тут же группируются и исходные данные удаляются(списки очищаются), иначе быстро переполняется память.
А цель использования потоков — получить больше сгруппированных данных(чтобы их объединить/просуммировать).

Я грешил на рандом, и комментировал его, работая лишь с начальной последовательностью, но производительность не улучшилась.


F>Расходы памяти на сам поток достаточно небольшие, и малозаметны на фоне общих расходов памяти приложения. А сколько там метод, работающий в потоке будет потреблять оперативки — это опять же зависит от коад метода.


Метод запускает методы передаваемого экземпляра класса, и в этих методах запускается достаточно много других методов создаваемых экземпляров других классов.
Тут у меня возник вопрос — все эти методы, они как бы хранятся в памяти в виде копий для каждого экземпляра класса, или копия для методов одна?
Т.е. если копия одна — может они конкурируют как то...
Отредактировано 11.02.2015 9:51 inevity . Предыдущая версия . Еще …
Отредактировано 11.02.2015 9:50 inevity . Предыдущая версия .
Отредактировано 11.02.2015 9:36 inevity . Предыдущая версия .
Отредактировано 11.02.2015 9:32 inevity . Предыдущая версия .
Отредактировано 11.02.2015 9:30 inevity . Предыдущая версия .
Re: Потоки, net, потеря производительности
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 11.02.15 15:01
Оценка:
Здравствуйте, inevity, Вы писали:

I>Но надеюсь опытные спецы без особого труда подскажут хотя бы где искать проблему.

Без особого труда подсказываю. Надо проблему искать в WorkClass. А лучше всего с профайлером.
Re[3]: Потоки, net, потеря производительности
От: WolfHound  
Дата: 11.02.15 20:54
Оценка:
Здравствуйте, inevity, Вы писали:

I>Тут у меня возник вопрос — все эти методы, они как бы хранятся в памяти в виде копий для каждого экземпляра класса, или копия для методов одна?

Одна. Но это не проблема.
Код и данные, которые потоки только читают можно без проблем использовать из нескольких потоков.

А ты можешь показать весь код? Тогда есть шанс, что кто-то поймёт что происходит.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Потоки, net, потеря производительности
От: tlp  
Дата: 11.02.15 21:25
Оценка:
Здравствуйте, inevity, Вы писали:

I>Почему нет увеличения размера программы в оперативной памяти соответственно количеству потоков?


Очевидно потому что это утверждение ложно.

Класс делал так, чтобы никаких общих данных не было, т.е. в поток попадает уникальный экземпляр класса (WorkObject)



Какая-то часть кода, которую вы вызываете, использует общие данные/обьекты и синхронизирует доступ к ним. Это могут быть какие-то общие глобальные переменные, синглтоны и т д или доступ к ресурсам с неявной синхронизацией (например, запись в файл, использование вызовов вроде printf, глобальные именованные мьютексы и т д)
Re[4]: Потоки, net, потеря производительности
От: inevity  
Дата: 12.02.15 00:20
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>А ты можешь показать весь код? Тогда есть шанс, что кто-то поймёт что происходит.


легко https://yadi.sk/d/Wj_8k3H-ea6Qd

Сначала я создал тему тут (но почти не было ответов)
http://it.mmcs.sfedu.ru/forum?func=view&amp;id=77607&amp;catid=27

Затем пришел ответ интересный вроде:

На двух ядрах без HyperThreading как-то плохо выявляется причина.
Профилировщик Visual Studio сообщает, что на двух потоках попадаются то там то сям участки, где поток ждет 1 миллисекунду. Таких участков набирается не более 200 за 10 секунд. По стеку вызовов явных причин не видно, все блокировки происходят где-то в недрах clr.dll или mscorlib.dll. Но на двух потоках программа еще довольно хорошо работает.
На четыре потока уже ядер не хватает. Уже потоки проводят огромное количество времени (половину) в заблокированном состоянии то там то сям. Скорее всего, где их операционная система прерывает чтобы дать следующий квант времени другому потоку, там профилировщик и фиксирует блокировку, тут уже особо и не посмотришь.

А было бы интересно посмотреть такой же отчет при эдак 20-30 потоках, когда лимит ускорения уже достигнут.

Пока не знаю, на что свалить вину, кроме кэша и памяти.
Re[5]: Потоки, net, потеря производительности
От: cures Россия cures.narod.ru
Дата: 12.02.15 01:05
Оценка:
Здравствуйте, inevity, Вы писали:

I>легко https://yadi.sk/d/Wj_8k3H-ea6Qd


Ох! Смешались в кучу кони, люди, и залпы тысячи орудий...
Если я понимаю правильно, основная работа должна происходить в makesession? Особых вычислений там не заметил (они тщательно замаскированы?), а вот new там хватает. Хип наверняка общий, за него идёт конкуренция.
Дельфи у меня нет, это то, что бросается в глаза.
Ещё подозрительны DoEvents, там возможно повторное вхождение в эти функции? Лучше бы логику UI и логику вычислений разнести, потоки по завершении могут дёргать UI колбэки для обновления состояния. Впрочем, об этом Вам там уже написали, Вы ответили, что влиять не должно.
Для более тщательного анализа лучше бы выделить главную вычислительную часть отдельно и тестировать вообще без UI.
Re[6]: Потоки, net, потеря производительности
От: inevity  
Дата: 12.02.15 01:32
Оценка:
Здравствуйте, cures, Вы писали:

C>Ох! Смешались в кучу кони, люди, и залпы тысячи орудий...

АХАХАХ! Да уж, это чистая правда! У меня схожие мысли, когда смотрю на код. Да и писал по вечерам, даже если что и мог сделать — уже даже этого не мог сделать нормально.
Вообще, сначала написал код, а потом подумал о потоках, опять пришлось притягивать за уши... Плюс результат нужен был быстрее, вот и получилось "я его слепила из того, что было".

C>Если я понимаю правильно, основная работа должна происходить в makesession? Особых вычислений там не заметил (они тщательно замаскированы?), а вот new там хватает. Хип наверняка общий, за него идёт конкуренция.

C>Дельфи у меня нет, это то, что бросается в глаза.

Да, основная работа там. New — не знал какой функционал потребуется в будущем, и все делал через классы(которые мог выделить логически). Затем на классы наворачивал функции и прочее.
Я и подумать не мог, что тут кроется проблема...
Особых вычислений, действительно, нет. Там генерация псевдослучайных чисел и логическая обработка с "расфасовкой" по объектам.

C>Ещё подозрительны DoEvents, там возможно повторное вхождение в эти функции? Лучше бы логику UI и логику вычислений разнести, потоки по завершении могут дёргать UI колбэки для обновления состояния. Впрочем, об этом Вам там уже написали, Вы ответили, что влиять не должно.


DoEvents уже сделал вообще "в тупую", т.к. после завершения потоков производительность не нужна вообще и никаких критических мест нет.

C>Для более тщательного анализа лучше бы выделить главную вычислительную часть отдельно и тестировать вообще без UI.

По-хорошему вообще надо было все делать не так... Но, надеюсь, профайлер поможет обнаружить проблему без переделывания кода.
Отредактировано 12.02.2015 1:43 inevity . Предыдущая версия . Еще …
Отредактировано 12.02.2015 1:41 inevity . Предыдущая версия .
Отредактировано 12.02.2015 1:40 inevity . Предыдущая версия .
Отредактировано 12.02.2015 1:36 inevity . Предыдущая версия .
Отредактировано 12.02.2015 1:34 inevity . Предыдущая версия .
Re[7]: Потоки, net, потеря производительности
От: Вячеслав Бенедичук Интернет  
Дата: 12.02.15 05:30
Оценка:
C>>Если я понимаю правильно, основная работа должна происходить в makesession? Особых вычислений там не заметил (они тщательно замаскированы?), а вот new там хватает. Хип наверняка общий, за него идёт конкуренция.
C>>Дельфи у меня нет, это то, что бросается в глаза.

I>Да, основная работа там. New — не знал какой функционал потребуется в будущем, и все делал через классы(которые мог выделить логически). Затем на классы наворачивал функции и прочее.

I>Я и подумать не мог, что тут кроется проблема...
I>Особых вычислений, действительно, нет. Там генерация псевдослучайных чисел и логическая обработка с "расфасовкой" по объектам.

Посмотри профайлером, как у тебя распределяетася память.
Выглядит так, что у тебя забивается хип, после чего стартует GC, который блокирует исполнение всех твоих потоков на время чистки памяти. Это очень сильно снижает производительность.

str+=s+','
myform.Text:=FormCaption+', done = '+ (((1000*i) div k)/10).ToString('#0.0')+ '%, Delta='+(abs(Table.EQ1-Table.EQ2)*100).ToString('#0.000')+', CNT='+Table.sameEQcount.ToString;
s1+=PatTextBoxes[i,j].Text;

— такие конструкции кушают память очень быстро и нерационально, так как строка иммутабельна, то каждый плюс дает новый экземпляр.
пользуйся string builder.
--
http://www.slideshare.net/vyacheslavbenedichuk
https://www.linkedin.com/in/vbenedichuk
Re[8]: Потоки, net, потеря производительности
От: inevity  
Дата: 12.02.15 06:29
Оценка:
Здравствуйте, Вячеслав Бенедичук, Вы писали:

ВБ>Посмотри профайлером, как у тебя распределяетася память.

ВБ>Выглядит так, что у тебя забивается хип, после чего стартует GC, который блокирует исполнение всех твоих потоков на время чистки памяти. Это очень сильно снижает производительность.

ВБ>str+=s+','

ВБ>myform.Text:=FormCaption+', done = '+ (((1000*i) div k)/10).ToString('#0.0')+ '%, Delta='+(abs(Table.EQ1-Table.EQ2)*100).ToString('#0.000')+', CNT='+Table.sameEQcount.ToString;
ВБ>s1+=PatTextBoxes[i,j].Text;

ВБ>- такие конструкции кушают память очень быстро и нерационально, так как строка иммутабельна, то каждый плюс дает новый экземпляр.

ВБ>пользуйся string builder.

Благодарю! (и всех других ответивших тоже)
Мысль о хипе, была высказана чуть ранее и в Вашем сообщении тоже.
Похоже, что проблема действительно в этом. Выглядит очень логично. — Основная работа у меня идет скорее с памятью.
Отредактировано 12.02.2015 6:35 inevity . Предыдущая версия . Еще …
Отредактировано 12.02.2015 6:31 inevity . Предыдущая версия .
Re[5]: Потоки, net, потеря производительности
От: WolfHound  
Дата: 12.02.15 09:20
Оценка:
Здравствуйте, inevity, Вы писали:

WH>>А ты можешь показать весь код? Тогда есть шанс, что кто-то поймёт что происходит.

I>легко https://yadi.sk/d/Wj_8k3H-ea6Qd
Не лепи код в одну строку. Читать не возможно.
    constructor; var i,j: integer; begin ShufflePosition:=0; Cards:=new List<TCard>; for j:=0 to 3 do for i:=2 to 14 do Cards.Add(new TCard(i,j)); rnd:=new System.Random; end;

Вот так гораздо лучше:
    constructor;
        var i, j: integer;
    begin
        ShufflePosition := 0;
        Cards := new List<TCard>;
        for j := 0 to 3 do
            for i := 2 to 14 do
                Cards.Add(new TCard(i, j));
        rnd := new System.Random;
    end;


Вот это квадратичный алгоритм с кошмарным количеством выделений памяти на ровном месте.
    procedure RemoveDeadCards(ADeadCards: String);
    begin ADeadCards := ADeadCards.ToUpper.Replace('C','c').Replace('D','d').Replace('H','h').Replace('S','s');
      for i:byte:=Cards.Count-1 downto 0 do if ADeadCards.Contains(Cards[i].ToString) then Cards.RemoveAt(i);
    end;


Памяти там у тебя выделяется действительно очень много.
Скорей всего именно в этом и проблема.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Потоки, net, потеря производительности
От: inevity  
Дата: 12.02.15 10:14
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Не лепи код в одну строку. Читать не возможно.

Сори, делал для себя, для меня это логический блок, чтобы не листать потом долго. Людям, конечно, такое читать, понятное дело, не очень.

WH>Вот это квадратичный алгоритм с кошмарным количеством выделений памяти на ровном месте.

WH>
WH>    procedure RemoveDeadCards(ADeadCards: String);
WH>    begin ADeadCards := ADeadCards.ToUpper.Replace('C','c').Replace('D','d').Replace('H','h').Replace('S','s');
WH>      for i:byte:=Cards.Count-1 downto 0 do if ADeadCards.Contains(Cards[i].ToString) then Cards.RemoveAt(i);
WH>    end;
WH>


А как подобные вещи правильней писать?

WH>Памяти там у тебя выделяется действительно очень много.

WH>Скорей всего именно в этом и проблема.

Наверняка! Я провел простые тесты, и смог увеличить предельную загрузку сервера с 18 до 30%, явно дело в памяти и/или сборщике мусора.
Re[7]: Потоки, net, потеря производительности
От: WolfHound  
Дата: 12.02.15 10:55
Оценка:
Здравствуйте, inevity, Вы писали:

I>Сори, делал для себя, для меня это логический блок, чтобы не листать потом долго. Людям, конечно, такое читать, понятное дело, не очень.

Через пол года ты сам перестанешь понимать, что там происходит.

I>А как подобные вещи правильней писать?

Там всё надо переписывать. И мне лень.
начать можно с этого:
  TCard = class 
    Number: byte; 
    Suit: byte; 
    constructor (ANumber: byte; ASuit: byte); begin Number := ANumber; Suit := ASuit; end;
    public
    function ToString: string; override; begin Result := CardNumbersString.Substring(number-2,1)+'cdhs'.Substring(suit,1); end;
  end;

1)Изменяем class на record. record'ы являются вальютипами и не создают объекты в куче. Делать это можно не всегда. Но в данном случае можно.
2)Заменяем пару Number и Suit на Number. Просто присваиваем каждой карте свой уникальный номер.
3)Заводим заранее заполненную таблицу с именами карт.
  TCard = record
    Number: byte; 
    constructor (ANumber: byte; ASuit: byte);
    begin
        Number := ANumber;
    end;
  public
    function ToString: string; override;
    begin
        Result := CardNumbersString[Number];
    end;
  end;

таким образом, мы убираем кучу выделений памяти.

I>Наверняка! Я провел простые тесты, и смог увеличить предельную загрузку сервера с 18 до 30%, явно дело в памяти и/или сборщике мусора.

Ты просто забиваешь память мусором и сборщику мусора приходится останавливать все потоки, чтобы убрать мусор.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: Потоки, net, потеря производительности
От: cures Россия cures.narod.ru
Дата: 12.02.15 11:56
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Ты просто забиваешь память мусором и сборщику мусора приходится останавливать все потоки, чтобы убрать мусор.


Дело не только в GC, память выделяется мелкими кусками, они имеют свойство сильно перемешиваться, соответственно каждый поток пишет в один и тот же участок памяти, для сохранения когеррентности процессору приходится организовывать между ними взаимодействие, что тоже очень дорого, причём не изредка, а постоянно. И вряд ли какой профилировщик это отловит, разве что oprofile или его аналог в винде.
Тут или надо озаботиться предварительным выделением всего, что нужно, или вообще разнести по разным процессам, раз общая память не нужна.
Re[9]: Потоки, net, потеря производительности
От: WolfHound  
Дата: 12.02.15 12:36
Оценка:
Здравствуйте, cures, Вы писали:

C>Дело не только в GC, память выделяется мелкими кусками, они имеют свойство сильно перемешиваться, соответственно каждый поток пишет в один и тот же участок памяти, для сохранения когеррентности процессору приходится организовывать между ними взаимодействие, что тоже очень дорого, причём не изредка, а постоянно. И вряд ли какой профилировщик это отловит, разве что oprofile или его аналог в винде.

В .NET своя куча в каждом потоке.
... << RSDN@Home 1.2.0 alpha 5 rev. 62>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: Потоки, net, потеря производительности
От: inevity  
Дата: 12.02.15 22:39
Оценка:
Здравствуйте, WolfHound, Вы писали:

I>>А как подобные вещи правильней писать?

WH>Там всё надо переписывать. И мне лень.
WH>начать можно с этого:

Благодарю!
А можно где-то почитать про подобные нюансы?

На счет памяти. Выходит, что я постоянно ПЕРЕсоздаю объекты(постоянное перераспределение памяти), но ведь это не обязательно и можно создать один раз,
и далее просто перезаписывать сами данные(без пересоздания), возможно, это главный момент(сборщику не будет работы во время работы потоков).

То, что памяти выделяется много — это можно терпеть, т.к. каши пока не просит, а при желании можно поработать с кодом.
Отредактировано 13.02.2015 4:20 inevity . Предыдущая версия .
Re[10]: Потоки, net, потеря производительности
От: Sinix  
Дата: 13.02.15 06:12
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>В .NET своя куча в каждом потоке.

Для каждого логического ядра, и то не для всех GC. Там вся аллокация (пока место есть) — один interlocked.Add(), нафиг perThread там не нужен.

По коду — его сначало надо начисто переписать, затем прогнать профайлером и смотреть на результаты.
Первое — чтобы не взрывать себе мозг при каждой ошибке, второе — чтобы самому научиться искать косяки, а не ждать поддержки на форуме.
Re[11]: Потоки, net, потеря производительности
От: cures Россия cures.narod.ru
Дата: 13.02.15 16:45
Оценка: -4
Здравствуйте, Sinix, Вы писали:

WH>>В .NET своя куча в каждом потоке.

S>Для каждого логического ядра, и то не для всех GC. Там вся аллокация (пока место есть) — один interlocked.Add(), нафиг perThread там не нужен.

Ну казалось бы логичным на каждый поток завести свой не очень большой пул, размером с метр, и выделять из него, и только когда кончится место — лочиться и выхватывать у системы новый кусок памяти. Но тогда не менее логичным кажется и в GC чистить прежде всего его, не останавливая другие потоки. А уж как там на самом деле, да ещё в разных реализациях, тем более в Дельфи — я понятия не имею, наверное WolfHound что-то знает и сможет поделиться с нами ссылками.

S>По коду — его сначало надо начисто переписать, затем прогнать профайлером и смотреть на результаты.


Ага, и очень желательно — на нормальном языке, а в идеале — и без всяких Нетов. Уже это может дать ускорение не хуже, чем 32 ведра на серванте простого тракториста

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


Ну товарищ вроде неофит, помочь не сложно. Но умиляет надежда, что сейчас профилер всё найдёт — и всё само исправится, ничего не придётся переписывать.
Re[12]: Потоки, net, потеря производительности
От: Sinix  
Дата: 13.02.15 18:36
Оценка:
Здравствуйте, cures, Вы писали:

S>>Для каждого логического ядра, и то не для всех GC. Там вся аллокация (пока место есть) — один interlocked.Add(), нафиг perThread там не нужен.

C>А уж как там на самом деле, да ещё в разных реализациях, тем более в Дельфи — я понятия не имею, наверное WolfHound что-то знает и сможет поделиться с нами ссылками.
Речь не о дельфи. У топикстартера pascalABC, реализация паскаля под .net. Ни одна из реализаций clr от MS не использует отдельную кучу под каждый поток. Этот подход в принципе не будет работать для generational gc.

S>>По коду — его сначало надо начисто переписать, затем прогнать профайлером и смотреть на результаты.

C>Уже это может дать ускорение не хуже, чем 32 ведра на серванте простого тракториста
Как показывает практика, до тех пор пока речь не идёт о совсем низкоуровневых вещах, язык играет последнюю роль в производительности. "Замена на нормальный язык" не даст выигрыша на порядок. Использование правильных алгоритмов — даст.


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

C>Но умиляет надежда, что сейчас профилер всё найдёт — и всё само исправится, ничего не придётся переписывать.
Не получится. Профайлер — это инструмент для обнаружения проблем, для починки придётся работать руками-головой.
Re: Потоки, net, потеря производительности
От: Igorxz  
Дата: 14.02.15 10:17
Оценка: -2
Здравствуйте, inevity, Вы писали:

I>Здравствуйте, друзья!


I>Заранее прощу прощения! Я сам тракторист, но черт меня дернул заняться программированием(еще и на паскале). Опишу ситуацию по мере сил.

I>Но надеюсь опытные спецы без особого труда подскажут хотя бы где искать проблему.

I>Проблема:........


вот так попробуй в конфиге сделать:

  <runtime>
    <gcServer enabled="true" />
  </runtime>


(у тебя же есть в паскале конфиг?)
Re[2]: Потоки, net, потеря производительности
От: Sinix  
Дата: 14.02.15 10:21
Оценка: +1
Здравствуйте, Igorxz, Вы писали:


I>вот так попробуй в конфиге сделать:

Не надо играться с шрифтами, пока не определил проблемное место и способ лечения. Не поможет.

Server gc тут как зелёнка при гангрене: и так зелёное, и так, разницы никакой.
Re[12]: Потоки, net, потеря производительности
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 14.02.15 11:51
Оценка: +1
Здравствуйте, cures, Вы писали:

C>Здравствуйте, Sinix, Вы писали:


WH>>>В .NET своя куча в каждом потоке.

S>>Для каждого логического ядра, и то не для всех GC. Там вся аллокация (пока место есть) — один interlocked.Add(), нафиг perThread там не нужен.

C>Ну казалось бы логичным на каждый поток завести свой не очень большой пул, размером с метр, и выделять из него, и только когда кончится место — лочиться и выхватывать у системы новый кусок памяти. Но тогда не менее логичным кажется и в GC чистить прежде всего его, не останавливая другие потоки. А уж как там на самом деле, да ещё в разных реализациях, тем более в Дельфи — я понятия не имею, наверное WolfHound что-то знает и сможет поделиться с нами ссылками.


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

Попробуй для начала ответить на простой вопрос. Если поток А выделил блок памяти, а потом передал в поток В, то как ты будешь сжимать кучу останавливая только А?
Re[3]: Потоки, net, потеря производительности
От: Igorxz  
Дата: 14.02.15 18:34
Оценка: -1
Здравствуйте, Sinix, Вы писали:

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



I>>вот так попробуй в конфиге сделать:

S>Не надо играться с шрифтами, пока не определил проблемное место и способ лечения. Не поможет.

S>Server gc тут как зелёнка при гангрене: и так зелёное, и так, разницы никакой.


Чего не надо?!? какая зеленка — это и есть один из способов лечения
Re[4]: Потоки, net, потеря производительности
От: Sinix  
Дата: 14.02.15 20:00
Оценка: +3
Здравствуйте, Igorxz, Вы писали:

S>>Server gc тут как зелёнка при гангрене: и так зелёное, и так, разницы никакой.


I>Чего не надо?!? какая зеленка — это и есть один из способов лечения

Ага-ага.
И аллокации лишние оно уберёт, и тормоза из-за использования List<T> без задания capacity, и обращение к контролам+AppDoEvents в рабочих потоках полечит.
Вы бы хоть код посмотрели для начала
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.