Re[39]: плохой язык C++ :)
От: prVovik Россия  
Дата: 22.03.06 15:12
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Челове явно сказл, что выделяет память под 8000 сообщений, что их размеры их равны,

Какие еще равные размеры?
Может ссылку дашь?

VD>и что память под них можно выделять из циклического буфера. Ты же мало того, что начал выискивать тайный смысл в его словах, но и подвигнул его на откроенный год о 8 000 сообщений по 4 Кб каждое. Нехитрый подсчет показывает, что такой объем данных через сеть в секунду можно пропихнуть если только она гигабитная. О тормозах памяти при таком расскладе можно забыть.

ЕЩЕ РАЗ ПОВТОРЯЮ МЕДЛЕННО: РЕЧЬ ИДЕТ О СЕРВЕРЕ.
И реально выделений есс-но было не 8к, а больше. Я их не считал.
лэт ми спик фром май харт
Re[40]: плохой язык C++ :)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.03.06 15:19
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>А исправил я пустячёк... заменил std::string на std::wstring и char на wchar_t. А то как-то не очень честно, ведь в дотнете char все же равен 2 байтам.


Имхо, это проблемы .Net-а, ведь речь шла о 4K сообщениях, а не о 8K сообщениях

VD>Я чуть-чуть поколдовал над тестом (мой и твоей реализацией) и у меня получились следующие результатаы...

VD>Для С++ (твой тест):
VD>
VD>simple alloc_objects
VD>duration: 7.077
VD>price: 0.35385
VD>alloc raw_vectors
VD>duration: 3.516
VD>price: 0.1758
VD>


А теперь посмотри, что ты выделил жирным и текст программы, которую ты запускал. duration -- это продолжительность 20(!) повторений теста, а вот price -- это усредненное время выполнения одного теста. И величина, как видишь, получается похожей на твой C# вариант.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[40]: плохой язык C++ :)
От: prVovik Россия  
Дата: 22.03.06 15:20
Оценка:
Здравствуйте, prVovik, Вы писали:

VD>>и что память под них можно выделять из циклического буфера. Ты же мало того, что начал выискивать тайный смысл в его словах, но и подвигнул его на откроенный год о 8 000 сообщений по 4 Кб каждое. Нехитрый подсчет показывает, что такой объем данных через сеть в секунду можно пропихнуть если только она гигабитная. О тормозах памяти при таком расскладе можно забыть.

V>ЕЩЕ РАЗ ПОВТОРЯЮ МЕДЛЕННО: РЕЧЬ ИДЕТ О СЕРВЕРЕ.
V>И реально выделений есс-но было не 8к, а больше. Я их не считал.
Тут проблема была в том, что стандартный виндосячий хип — это тормоз жуткий.
лэт ми спик фром май харт
Re[42]: плохой язык C++ :)
От: igna Россия  
Дата: 22.03.06 15:21
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Блин, слава богу, что экономисты вроде igna не проектируют библиотек. А то мы так бы ижли с ручным выделеним буферов под каждый чих.



ReadLine возвращающий String и ReadLine читающий в переданный ему StringBuilder вполне могли бы сосуществовать. И каждый жил бы в соответствии с чем-то своим. Правда да, для приверженцев очередной Религии Программирования это конечно кощунство.
Re[40]: плохой язык C++ :)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.03.06 15:22
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Извини, но не верю. Особенно после сказок про 8 000 * 4К сообещений принимаемых по сети.


А ты у AndrewVK пораспрашивай про производительность различных сетей (см. например, что он мне сам говорил: http://www.rsdn.ru/Forum/Message.aspx?mid=1781228&amp;only=1
Автор: AndrewVK
Дата: 14.03.06
).


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[39]: плохой язык C++ :)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.03.06 15:38
Оценка:
Здравствуйте, VladD2, Вы писали:

E>>2VladD2: а минус за что? С чем конкретно ты не согласен?


VD>Челове явно сказл, что выделяет память под 8000 сообщений, что их размеры их равны, и что память под них можно выделять из циклического буфера.


Вот, что человек сказал
Автор: prVovik
Дата: 22.03.06

Это был проект сетевого движка для MMORPG. Приходило 8к сообщений (разного размера) в секунду и управление памятью как раз было узким местом.


Т.е. человек говорил про обработку 8K сообщений в секунду. А не о простом укладывании куда-то.

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


А если сеть гигабитная? Это что редкость?
А если это сеть через FireWire?
А если это ATM сеть?
Или какой-нибудь InfiniBand?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[40]: плохой язык C++ :)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 22.03.06 16:22
Оценка:
Здравствуйте, VladD2, Вы писали:

Результаты под Linux (Slackware 10.2, ядро 2.6.13, gcc 3.3.6), машина та же, что и в моих Windows-тестах.
simple alloc_objects
duration: 3.26
price: 0.163
alloc raw_vectors
duration: 0.61
price: 0.0305


Только я заменил в версии для Linux-а wchar_t на unsigned short, т.к. в Linux-е wchar_t -- это 4-ре байта.


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[41]: плохой язык C++ :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.03.06 16:54
Оценка:
Здравствуйте, eao197, Вы писали:

VD>>Извини, но не верю. Особенно после сказок про 8 000 * 4К сообещений принимаемых по сети.


E>А ты у AndrewVK пораспрашивай про производительность различных сетей (см. например, что он мне сам говорил: http://www.rsdn.ru/Forum/Message.aspx?mid=1781228&amp;only=1
Автор: AndrewVK
Дата: 14.03.06
).


Ненадо переводить стрелки. Мы обсуждаем конкретную "оптимизацию". По-моему, очевидно, что никакая оптимизация там была не нужна. Да и сам рссказ на правду не тянет. 32 метра в игрушках по сети не передается. Даже действительно интерактивные игры вроде Ку передают в худшем случае килобайты в секунду. И просходит это потому, что иначе никто не будет играть в такие игры по Интернету.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[40]: плохой язык C++ :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.03.06 16:54
Оценка:
Здравствуйте, eao197, Вы писали:

E>Вот, что человек сказал
Автор: prVovik
Дата: 22.03.06

E>

E>Это был проект сетевого движка для MMORPG. Приходило 8к сообщений (разного размера) в секунду и управление памятью как раз было узким местом.


E>Т.е. человек говорил про обработку 8K сообщений в секунду. А не о простом укладывании куда-то.


Ага. И рядом же дальше пошел рассказывать, что каждое из них было по 4Кб. В общем, извини, но это уже не смешно.

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


E>А если сеть гигабитная? Это что редкость?


MMORPG == игрушка. Если игрушка требует гигабайтной сети, то ее авторы разарятся, так как они на фиг никому не упала. К тому же MMORPG — это еще и не сильно интерактивная вещь.

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

E>А если это сеть через FireWire?

E>А если это ATM сеть?
E>Или какой-нибудь InfiniBand?

Ты уверен, что понимашь о чем говоришь?
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[40]: плохой язык C++ :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.03.06 16:54
Оценка:
Здравствуйте, prVovik, Вы писали:

VD>>Челове явно сказл, что выделяет память под 8000 сообщений, что их размеры их равны,

V>Какие еще равные размеры?
V>Может ссылку дашь?

Сори, про равные размеры сказал: igna
Автор: igna
Дата: 21.03.06
.

VD>>и что память под них можно выделять из циклического буфера. Ты же мало того, что начал выискивать тайный смысл в его словах, но и подвигнул его на откроенный год о 8 000 сообщений по 4 Кб каждое. Нехитрый подсчет показывает, что такой объем данных через сеть в секунду можно пропихнуть если только она гигабитная. О тормозах памяти при таком расскладе можно забыть.

V>ЕЩЕ РАЗ ПОВТОРЯЮ МЕДЛЕННО: РЕЧЬ ИДЕТ О СЕРВЕРЕ.
V>И реально выделений есс-но было не 8к, а больше. Я их не считал.

Да какая разница о чем? Для сообщения размером в 4 Кб нужно ровно 4Кб памяти. Спроси у Дворкина если мне не веришь.

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

Если ты говоришь правду, то вам нужно было заниматься оптимизацией передачи данных по сети, а не выделением памяти.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[41]: плохой язык C++ :)
От: VladD2 Российская Империя www.nemerle.org
Дата: 22.03.06 16:54
Оценка:
Здравствуйте, prVovik, Вы писали:

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


Максимум в 2-4 раза хуже лушчих реализаций. Порой даже ничем не хуже.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[42]: плохой язык C++ :)
От: Cyberax Марс  
Дата: 22.03.06 17:47
Оценка:
VladD2 wrote:
> Ненадо переводить стрелки. Мы обсуждаем конкретную "оптимизацию".
> По-моему, очевидно, что никакая оптимизация там была не нужна. Да и сам
> рссказ на правду не тянет. 32 метра в игрушках по сети не передается.
Это _MMORPG_ с кучей клиентов.

1000 клиентов на сервер — вполне нормально, а это дает всего 3.2кб/сек
на пользователя. А это модемная скорость.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[41]: плохой язык C++ :)
От: Cyberax Марс  
Дата: 22.03.06 17:48
Оценка:
VladD2 wrote:
> MMORPG == игрушка. Если игрушка требует гигабайтной сети, то ее авторы
> разарятся, так как они на фиг никому не упала. К тому же MMORPG — это
> еще и не сильно интерактивная вещь.
В MMORPG обычно делают разные login- и game-серверы, так что канал в
1Гбит между ними — вполне нормально.
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[41]: плохой язык C++ :)
От: WolfHound  
Дата: 22.03.06 17:52
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>MMORPG == игрушка. Если игрушка требует гигабайтной сети, то ее авторы разарятся, так как они на фиг никому не упала. К тому же MMORPG — это еще и не сильно интерактивная вещь.

У MMORPG есть не только клиент. Но и сервер. prVovik говорит про сервер.
А там и нагрузка не маленькая. Хотя лично я бы сервер для MMORPG делал в расчете на кластер. Всеравно масштабируемость нужна на случай если игра популярной станет.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[41]: плохой язык C++ :)
От: prVovik Россия  
Дата: 22.03.06 18:09
Оценка:
Здравствуйте, VladD2, Вы писали:


VD>Да какая разница о чем? Для сообщения размером в 4 Кб нужно ровно 4Кб памяти. Спроси у Дворкина если мне не веришь.

Да, на счет 4кб я неверно выразился. По ТЗ это был максимальный размер сообщения.

VD>Если ты говоришь правду, то вам нужно было заниматься оптимизацией передачи данных по сети, а не выделением памяти.

Я данными не занимался. Было ТЗ с 8к сообщений и макс размер 4к. Все. На остальное мне было наплевать.
лэт ми спик фром май харт
Re[42]: плохой язык C++ :)
От: prVovik Россия  
Дата: 22.03.06 18:18
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Хотя лично я бы сервер для MMORPG делал в расчете на кластер. Всеравно масштабируемость нужна на случай если игра популярной станет.

Да мы сервер и не писали. Только сетевой движек.
лэт ми спик фром май харт
Re[43]: плохой язык C++ :)
От: Дарней Россия  
Дата: 23.03.06 02:30
Оценка:
Здравствуйте, igna, Вы писали:

I>ReadLine возвращающий String и ReadLine читающий в переданный ему StringBuilder вполне могли бы сосуществовать. И каждый жил бы в соответствии с чем-то своим. Правда да, для приверженцев очередной Религии Программирования это конечно кощунство.


Это никому не нужно. А кому это таки нужно, те пишут на MC++
Универсальных инструментов не бывает.
... << RSDN@Home 1.1.4 stable rev. 510>>
Всех излечит, исцелит
добрый Ctrl+Alt+Delete
Re[44]: плохой язык C++ :)
От: igna Россия  
Дата: 23.03.06 06:27
Оценка: +1 :)
Здравствуйте, Дарней, Вы писали:

Д>Это никому не нужно.



Точнее, это никому не должно быть нужно!
Re[40]: плохой язык C++ :)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.03.06 10:15
Оценка: 18 (3)
Здравствуйте, VladD2.

Решил еще раз вернуться к данному тесту. Во-первых, обнаружил ошибку -- в тесте с raw-векторами при выходе из цикла не уничтожались элементы. Во-вторых, добавил тест, где raw-вектора сохраняются в std::vector нужной размерности, а не в std::list (т.к. std::list может для каждого элемента динамически создавать дополнительный внутренний объект для провязывания в список). В-третьих, реализовал простейший менеджер памяти, заточенный для конкретно этой задачи и переопределил с его помощью new/delete.

Замерял производительность на Visual C++ v.7.1 (компиляция через 'cl -GX -O2') и Digital Mars C++ v.8.42 (компиляция через 'dmc -Ae -o').
Вот результаты со стандарным распределителем памяти:
Visual C++
simple alloc_objects
duration: 16.115
price: 0.80575
alloc raw_vectors
duration: 6.153
price: 0.30765
alloc raw_vectors_in_vectors
duration: 5.637
price: 0.28185

Digital Mars C++
simple alloc_objects
duration: 8.86
price: 0.443
alloc raw_vectors
duration: 0.812
price: 0.0406
alloc raw_vectors_in_vectors
duration: 0.516
price: 0.0258


А вот результаты с собственным распределителем памяти:
Visual C++
simple alloc_objects
duration: 5.527
price: 0.27635
alloc raw_vectors
duration: 0.157
price: 0.00785
alloc raw_vectors_in_vectors
duration: 0.125
price: 0.00625

Digital Mars C++
simple alloc_objects
duration: 6.547
price: 0.32735
alloc raw_vectors
duration: 0.281
price: 0.01405
alloc raw_vectors_in_vectors
duration: 0.157
price: 0.00785


Т.е. для Visual C++ применение собственного распределителя памяти, заточенного под конкретную задачу дало прирост в ~40 раз (0.007 против 0.307, и 0.006 против 0.281). Для Digital Mars C++ прирост не так существеннен -- всего ~4 раза. Но ведь все это без изменения исходников самого теста. Просто так на ровном месте взяли и увеличили скорость в несколько раз. Разумеется не бесплатно, но об этом чуть ниже.

А вот под Linux-ом результаты были интереснее. Во-первых, оказалось, что g++ v.3.3.6 и его C++ библиотека требует выделять память большими кусками, чем Visual C++ и Digital Mars C++. В моем распределителе памяти изначально предполагалось, что будет не более 128 блоков по 8K каждый. В случае же с g++ пришлось размер блока увеличивать до 16Kb. В результате тест с std::string на стандартном распределителе памяти выиграл у моего распределителя. Зато в остальных случаях мой распределитель дал увеличение производительности, но всего в два раза.

Какой ценой дался этот прирост в скорости? Ну, во-первых, привязкой распределителя к конкретным условиям. А именно то, что в самом худшем случае не может быть больше 100 блоков размером ~8K. Если это условие нарушается, то программа просто перестает работать. Во-вторых, расходом памяти. Распределитель сразу создает необходимые буфера для размещения блоков. В третьих, трудозатратами. На создание распределителя (точнее, нескольких его вариаций) ушло ~2-2.5 часа (главным образом потому, что начал я его делать вечером после работы, совершил поэтому несколько глупых ошибок, которые долго вылавливал). В-четвертых, выяснилось, что кроме того, что распределитель оказался привязанным к конкретной задаче, он еще не очень хорошо переносится на другие платформы/компиляторы, что очень не приятно.

Но, если есть необходимость выжать максимальную скорость для конкретной задачи на конкретной платформе (прирост в 40 раз для Visual C++ -- это серьезно, однако), то цена вполне умеренная.

Кстати, на полном серьезе, без подколок. А как увеличить производительность конкретно этого теста на C# без переделки исходников теста?


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Re[41]: плохой язык C++ :)
От: eao197 Беларусь http://eao197.blogspot.com
Дата: 23.03.06 10:20
Оценка:
Исходники.



Файл теста
#include <iostream>
#include <list>
#include <vector>
#include <string>
#include <algorithm>
#include <ctime>
 
typedef unsigned short TYPE;
static const int Count = 80000;
 
template< class T >
void
run_and_measure(
                T functor )
{
  const unsigned int cycles = 20u;
  std::clock_t start, finish;
 
  start = std::clock();
  for( unsigned int i = 0; i != cycles; ++i )
    functor();
  finish = std::clock();
 
  double duration = double( finish - start ) / CLOCKS_PER_SEC;
  double price = duration / cycles;
  std::cout
    << "duration: " << duration << std::endl
    << "price: " << price << std::endl;
}
 
void
alloc_objects()
{
  typedef std::list< std::wstring > list_t;
 
  list_t list;
 
  for( unsigned int i = 0; i != Count; ++i )
  {
    list.push_back( std::wstring(i % 4 * 1024, 0 ) );
 
    if( !( i % 100 ) )
      list.clear();
  }
}
 
void
raw_vector_destroyer( TYPE * p )
{
  delete[] p;
}

void
alloc_raw_vectors()
{
  typedef std::list< TYPE * > list_t;
 
  list_t list;
 
  for( unsigned int i = 0; i != Count; ++i )
  {
    list.push_back( new TYPE[ i % 4 * 1024 ] );
 
    if( !( i % 100 ) )
    {
      std::for_each( list.begin(), list.end(), raw_vector_destroyer );
      list.clear();
    }
  }

  std::for_each( list.begin(), list.end(), raw_vector_destroyer );
}

void
alloc_raw_vectors_in_vectors()
{
    typedef std::vector< TYPE * > list_t;

    list_t list;
    list.reserve( 100 );

    for( unsigned int i = 0; i != Count; ++i )
    {
        list.push_back( new TYPE[ i % 4 * 1024 ] );

        if( !( i % 100 ) )
        {
            std::for_each( list.begin(), list.end(), raw_vector_destroyer );
            list.clear();
        }
    }

  std::for_each( list.begin(), list.end(), raw_vector_destroyer );
}
 
int
main()
{
  std::cout << "simple alloc_objects" << std::endl;
  run_and_measure( alloc_objects );
 
  std::cout << "alloc raw_vectors" << std::endl;
  run_and_measure( alloc_raw_vectors );
 
  std::cout << "alloc raw_vectors_in_vectors" << std::endl;
  run_and_measure( alloc_raw_vectors_in_vectors );
  
  return 0;
}




Вспомогательные классы для распределителя памяти, файл mem_mgr.hpp:
#if !defined( MEM_MGR_HPP )
#define MEM_MGR_HPP

#include <stdexcept>
#include <cstdlib>
#include <cstdio>

using namespace std;

template< class T, unsigned int Capacity >
class cyclic_queue_t
    {
    private :
        T    m_begin[ Capacity ];
        T *    m_end;
        T *    m_head;
        T *    m_tail;
        unsigned int m_count;

    public :
        cyclic_queue_t()
            :    m_end( m_begin + Capacity )
            ,    m_head( m_begin )
            ,    m_tail( m_begin )
            ,    m_count( 0 )
            {}

        void
        push( T v )
            {
                if( m_count == Capacity )
                    {
                        fprintf( stderr, "cyclic_queue overflow!\n" );
                        abort();
                    }
                else
                    ++m_count;

                *m_tail = v;
                if( (++m_tail) == m_end )
                    m_tail = m_begin;
            }

        T
        head() const
            {
                return *m_head;
            }

        void
        pop()
            {
                if( !m_count )
                    {
                        fprintf( stderr, "cyclic_queue underflow!\n" );
                        abort();
                    }
                else
                    ++m_count;

                if( (++m_head) == m_end )
                    m_head = m_begin;
            }
    };

template< unsigned int Block_size, unsigned int Capacity >
class mem_pool_t
    {
    private :
        char    m_buf[ Block_size * Capacity ];
        const char * const m_right;

        cyclic_queue_t< char *, Capacity >    m_free_blocks;
        
    public :
        mem_pool_t()
            :    m_right( m_buf + Block_size * Capacity )
            {
                for( unsigned int i = 0; i != Capacity; ++i )
                    m_free_blocks.push( m_buf + Block_size * i );
            }

        char *
        alloc( unsigned int object_size )
            {
                if( Block_size < object_size )
                    {
                        fprintf( stderr, "mem_pool<%u,%u>: object_size: %u\n",
                                Block_size,
                                Capacity,
                                object_size );
                        throw std::bad_alloc();
                    }

                char * r = m_free_blocks.head();
                m_free_blocks.pop();

                return r;
            }

        bool
        dealloc( char * p )
            {
                if( m_buf <= p && p < m_right )
                    {
                        m_free_blocks.push( p );
                        return true;
                    }

                return false;
            }

    private :
        mem_pool_t( const mem_pool_t & o );
        mem_pool_t & operator=( const mem_pool_t & o );
    };

template<
    unsigned int Min_block_size,
    unsigned int Min_Capacity,
    unsigned int Max_block_size,
    unsigned int Max_Capacity >
class mem_mgr_t
    {
    public :
        mem_mgr_t()
            {}

        char *
        alloc( unsigned int size )
            {
                if( size <= Min_block_size )
                    return m_min_pool.alloc( size );

                return m_max_pool.alloc( size );
            }

        void
        dealloc( char * ptr )
            {
                if( !m_min_pool.dealloc( ptr ) )
                    m_max_pool.dealloc( ptr );
            }

    private :
        mem_pool_t< Min_block_size, Min_Capacity >    m_min_pool;
        mem_pool_t< Max_block_size, Max_Capacity >    m_max_pool;

    private :
        mem_mgr_t( const mem_mgr_t & o );
        mem_mgr_t & operator=( const mem_mgr_t & o );
    };

#endif




Сам распределитель памяти (custom_new.cpp):
#include "mem_mgr.hpp"

typedef mem_mgr_t< 128, 512, 8 * 1024, 128 > mem_manager_t;

static mem_manager_t &
manager()
    {
        static mem_manager_t m;
        return m;
    }

void *
operator new( unsigned int size ) { return manager().alloc( size ); }

void *
operator new[]( unsigned int size ) { return manager().alloc( size ); }

void
operator delete( void * p ) { manager().dealloc( reinterpret_cast< char * >( p ) ); }

void
operator delete[]( void * p ) { manager().dealloc( reinterpret_cast< char * >( p ) ); }


SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.