|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Есть потребность в реализации высокопроизводительного алгоритма для математических вычислений на основе данных MSSQL. Результаты вычислений так же сохраняются в MSSQL. Первая версия алгоритма реализована на T-SQL. Оптимизация программы показала невозможность избавиться от операций записи в журнале транзакций даже при отказе от использования физических таблиц в процессе расчета. Вывод - вынести расчет за пределы SQL Server. Вторая версия алгоритма реализована на C# в виде CLR-сборки (Safe/DLL) под .Net 3.5. Производительность повысилась на несколько порядков. Однако ряд ограничений C# не позволяет добиться максимума производительности. 1. Сборщик мусора не позволяет самостоятельно удалять объекты, а их в процессе вычислений создается целая куча -> перерасход памяти. 2. Тип структур является типом данных и не может быть использован для построения индексных массивов (с элементами типа ссылки на структуру), что приводит к использованию классов вместо структур, а значит перерасходу памяти и возможному снижению производительности. 3. Требуется кодогенерация (переопределение математических функций) при создании экземпляра объекта. В C# - это делегаты, анонимные и лямбда-методы. В С++ это просто ссылка на функцию. Существует большое отличие с точки зрения производительности при использовании этих подходов. 4. Судя по тестам в Интернете C# существенно уступает С++ в производительности математических программ. Вывод - сделать CLR-сборку на C++. Проблема в том, что в VS2012 ultimate я не нашел типа проекта SQL CLR для VC++. Есть только шаблон SQL Server для C# и VB.NET. Когда я пытался собирать DLL на базе шаблона C++ CLR, то какие бы я ни ставил настройки компилятора, MSSQL2008 всегда отказывался импортировать сборку по самым разным причинам. Вопросы: 1. Что думаете по поводу описанных выше недостатков C#. Я не писал на нем ранее, поэтому могу многого не знать и делать неверные выводы. 2. Был ли опыт создания CLR-сборок для MSSQL на C++? На MSDN есть примеры кода для VS2008, которые не работают в VS2012. Неужели нужно даунгрейдить VS??? 3. Стоит ли использовать связку MSSQL->CLR на C#->DLL на C++? Здесь C# будет использоваться только для обращения к БД и передаче данных в DLL на C++ для вычислений. Буду признателен, если укажете ссылки на тематические статьи в Интернете или примеры кода/настроек компилятора VC++. Спасибо! ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2013, 15:25 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2013, 16:00 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
xstoredandreybs, Я бы не заморачивался с CLR а создал бы обычную extended stored procedure на C Я тоже сначала думал проапгрейдить SQL до 2012 и использовать его возможности инлайн-процедур. Но одной процедурой не обойтись. И сохранять промежуточные результаты нужно в независимой области памяти для быстрого повторного обращения к ним. Все таки это должна быть внешняя библиотека. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2013, 16:23 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsИ сохранять промежуточные результаты нужно в независимой области памяти для быстрого повторного обращения к ним. ещё один источник геморроя с CLR ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2013, 16:31 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsИ сохранять промежуточные результаты нужно в независимой области памяти для быстрого повторного обращения к ним. ещё один источник геморроя с CLR Проблема только в неуправляемости процессом освобождения памяти. Там есть свои "лазейки", но в С++ это делается просто и наглядно. Поэтому и хочется найти возможность собрать CLR-сборку на С++. ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2013, 16:41 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs, соберите её без всяких визардов, как unsafe регистрируйте на сервере ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2013, 16:46 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилandreybs, соберите её без всяких визардов, как unsafe регистрируйте на сервере Пробовал, не получилось. SQL Server в этом случае ругается, что сборка не является нативной .NET (хотя я использовал библиотеки .Net 2.0.0.0). ... |
|||
:
Нравится:
Не нравится:
|
|||
27.07.2013, 17:12 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsSQL Server в этом случае ругается, что сборка не является нативной .NET регистрируемая сборка должна компилироваться с /clr:pure, а дальше эта сборка может уже обращаться к нормальному коду через P/Invoke ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 00:58 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsxstoredandreybs, Я бы не заморачивался с CLR а создал бы обычную extended stored procedure на C Я тоже сначала думал проапгрейдить SQL до 2012 и использовать его возможности инлайн-процедур. Но одной процедурой не обойтись. И сохранять промежуточные результаты нужно в независимой области памяти для быстрого повторного обращения к ним. Все таки это должна быть внешняя библиотека. extended stored procedure (XP) и есть внешняя библиотека. Или внутренняя. Что ты вообще понимаешь под "внешностью" или "внутренностью"? XP -- это .dll, других библиотек особенно и не бывает. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 11:29 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsИзопропилпропущено... ещё один источник геморроя с CLR Проблема только в неуправляемости процессом освобождения памяти. Там есть свои "лазейки", но в С++ это делается просто и наглядно. Поэтому и хочется найти возможность собрать CLR-сборку на С++. А тебе зачем собственно CLR ? ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 11:31 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsSQL Server в этом случае ругается, что сборка не является нативной .NET регистрируемая сборка должна компилироваться с /clr:pure, а дальше эта сборка может уже обращаться к нормальному коду через P/Invoke Начиная с MSSQL2005 это не поддерживается для VC++, если верить MSDNу ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 11:43 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
MasterZivandreybsпропущено... Проблема только в неуправляемости процессом освобождения памяти. Там есть свои "лазейки", но в С++ это делается просто и наглядно. Поэтому и хочется найти возможность собрать CLR-сборку на С++. А тебе зачем собственно CLR ? Потому что вызов пересчета должен происходить изнутри SQL Server, а он использует либо CLR, либо unsafe сборки. Последнее заколебешься дебагить в случае ошибки. Хотя и это ограничение можно обойти, собрав простое консольное приложение на С++ (в перспективе виндовс-сервис), которое лезет в сиквел и делает тоже самое, что и CLR на C#. Но тут сложность - как управлять этим консольным приложением. В конечном счете основную часть кода можно будет вынести в DLL и дебагить ее с помощью вызова из консольного приложения, а в рабочем режиме эта DLL будет цепляться к SQL как unsafe сборка с external или unrestricted access. Как то так, но до этого еще не скоро. Сначала отлажу алгоритм на C# и посмотрю на результаты. Может овчинка выделки не стоит... ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 11:57 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsНачиная с MSSQL2005 это не поддерживается для VC++, если верить MSDNу Поддерживается (сборки /clr:pure) UNSAFE enables assemblies unrestricted access to resources, both within and outside an instance of SQL Server. Code running from within an UNSAFE assembly can call unmanaged code. http://msdn.microsoft.com/en-us/library/ms189524.aspx P.S. крики о deprecated extended stored procedure слышны уже много лет ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 12:03 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsНо тут сложность - как управлять этим консольным приложением. andreybsМожет овчинка выделки не стоит... в вашем случае - похоже не стоит. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 12:09 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsНачиная с MSSQL2005 это не поддерживается для VC++, если верить MSDNу Поддерживается (сборки /clr:pure) Технически да, поддерживаются, но с целым рядом ограничений , которые в моем случае не позволят обеспечить прямое взаимодействие SQL<->DLL, только через интерфейсную прослойку SQL<->DLL/CLR<->DLL/Unmanaged. Это возможно, но очень геморно с точки зрения дебагинга, о чем я писал выше. Если проигнорировать ограничения, то при импорте такой DLL/CLR MSSQL выдаст ошибку - "unsupported clr code", а если /pure заменить на /safe, то даже не используя элементы unmanaged code все равно при импорте вылетает ошибка " assembly not supported " вне зависимости от того, на базе какой версии .Net это все собрано. ИзопропилUNSAFE enables assemblies unrestricted access to resources, both within and outside an instance of SQL Server. Code running from within an UNSAFE assembly can call unmanaged code. http://msdn.microsoft.com/en-us/library/ms189524.aspx P.S. крики о deprecated extended stored procedure слышны уже много лет Да понятно, но лично я не встречал юзабельных возможностей по поддержке deprecated SP в mssql. Говорят, в 2012 они тали лучше. Не знаю, посмотрим. Но судя по документации, в которой нет примеров на c++, только c# и asp.net, Майкрософт развивает свою технологию clr в связке с .Net и им нафиг сдалось поддерживать c++ с его unmanaged кодом. Так что писать библиотеки для mssql на c++ становится все сложнее и сложнее. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 13:31 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsХотя и это ограничение можно обойти, собрав простое консольное приложение на С++ (в перспективе виндовс-сервис), соберите клиентское приложение, не насилуйте сервер. andreybsНо тут сложность - как управлять этим консольным приложением это существенно проще, чем заставить сервер выполнять не свойственную ему работу Вопрос замены сервера на PostgeSQL не рассматривался? ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 14:28 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилВопрос замены сервера на PostgeSQL не рассматривался? Не рассматривался. В MSSQL реализованы алгоритмы обработки данных, на базе которых далее производятся вычисления. Объемы данных довольно большие. Тут нужна мощная СУБД. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 16:37 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs, Про С++ тут нет ничего. Перенесу тему в C#, если нет возражений. ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 20:26 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
MasterZivandreybs, Про С++ тут нет ничего. Перенесу тему в C#, если нет возражений. Не возражаю. Модератор: Тема перенесена из форума "C++". ... |
|||
:
Нравится:
Не нравится:
|
|||
28.07.2013, 23:25 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs, что приводит к использованию классов вместо структур, а значит перерасходу памяти и возможному снижению производительности. сколько байтов считали? Добавляет ли readonly property к размеру класса? ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2013, 11:10 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsНачиная с MSSQL2005 это не поддерживается для VC++, если верить MSDNу Поддерживается (сборки /clr:pure) UNSAFE enables assemblies unrestricted access to resources, both within and outside an instance of SQL Server. Code running from within an UNSAFE assembly can call unmanaged code. http://msdn.microsoft.com/en-us/library/ms189524.aspx P.S. крики о deprecated extended stored procedure слышны уже много лет крики то слышны, но как обычно будет версия, в которой это уже не поддерживается. Я бы не делал ESP. SQLCLR есть и надо пользоваться. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2013, 11:22 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
WinnipuhSQLCLR есть и надо пользоваться. так топикстартеру не нравится. ... |
|||
:
Нравится:
Не нравится:
|
|||
29.07.2013, 11:36 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилandreybs, что приводит к использованию классов вместо структур, а значит перерасходу памяти и возможному снижению производительности. сколько байтов считали? Добавляет ли readonly property к размеру класса? Точно не считал, но оптимизировал как мог, чтобы сохранить читабельность кода при минимуме размеров. В итоге получилась примерно такая модель: struct D { ... 5-7 переменных типа Int32 и Double } Class C { T Parent; // ссылка на родительский объект List<T> Links; // 10-20 связей на каждый объект D Data; // структура с данными C(...) { конструктор } } Выделил 4 типа данных T, для каждого из которых применил подобную модель. Всего одновременно живет до 1000 объектов (пока, в перспективе до 10000). За счет перекрестных ссылок все данные представлены одновременно в иерархическом/сетевом (для вычислений) и плоском представлении (для импорта/экспорта). Все управление классами делается на базе внешнего статического класса (экономим на таблице методов в каждом классе). Использовать структуры не получится, т.к. для создания перекрестных ссылок нужно ссылаться на объект из нескольких индексных массивов одновременно. В этом все деле меня больше всего интересует освобождение памяти после отчуждения объектов (на примере класса выше): 1. Нужно ли ставить Parent=null, чтобы разорвать сильные связи объектов и облегчить работу сборщика мусора. 2. Нужно ли ставить Links.Capacity=0 после очистки массива, чтобы высвободить память для повторного использования новым объектом. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 00:18 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилWinnipuhSQLCLR есть и надо пользоваться. так топикстартеру не нравится. Я не против. Но хотел бы сделать это на С++. Но собрать сборку, которую схавает SQL пока не получилось. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 00:22 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsоптимизировал как мог, чтобы сохранить читабельность кода при минимуме размеров не торопитесь с оптимизацией кода - оптимизируйте сначала алгоритм andreybsВыделил 4 типа данных T, для каждого из которых применил подобную модель особого смысла в выделении типа D - не вижу. Каковы отношения между четырьмя типами T и C? andreybsВсего одновременно живет до 1000 объектов (пока, в перспективе до 10000). 10000 - это очень мало. andreybsВсе управление классами делается на базе внешнего статического класса (экономим на таблице методов в каждом классе). ничего не экономим - все экземпляры класса используют одну общую таблицу методов andreybs1. Нужно ли ставить Parent=null, чтобы разорвать сильные связи объектов и облегчить работу сборщика мусора. облегчить таким способом нельзя. Если на экземпляр класса в программе нет никаких ссылок - мусоросборщика не волнует, на кого ссылается этот экземпляр. Рихтера почитайте. andreybs2. Нужно ли ставить Links.Capacity=0 после очистки массива, чтобы высвободить память для повторного использования новым объектом. нет, не нужно. Capacity влияет только на начальное выделение памяти для списка ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 07:49 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsНо хотел бы сделать это на С++. Но собрать сборку, которую схавает SQL пока не получилось. и не получится. MSSQL схавает c++ только сборку safe или pure.Смешаную - никак. А по возможностям в этом случае не будет разницы между managed c++ и c# А вообще-то c# поддерживает работу с неуправляемыми указателями ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 07:54 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилandreybsоптимизировал как мог, чтобы сохранить читабельность кода при минимуме размеров не торопитесь с оптимизацией кода - оптимизируйте сначала алгоритм Согласен. Но у меня закончились идеи. Сам по себе алгоритм достаточно прост. Он представляет из себя множество одинаковых операций умножения и сложения и взятия экспоненты. Операции выполняются последовательно, некоторые в качестве параметров используют результаты предыдущих вычислений. Операции агрегируются в группы по нескольким уровням. На С++ я бы сделал длиннющий одномерный массив double Arg[] и "массив операций" трех аргументов (операция, аргумент А, аргумент Б, аргумент Б). Каждый аргумент - это ссылка на элемент из Arg[]. Каждая операция - это поле int или byte над тремя аргументами: А=F(В,С). Таким образом группу всех вложенных циклов (как сейчас) можно было бы развалить в одну длиннющую портянку элементарных операций, выполняемых последовательно. И такая портянка вызывалась бы много-много раз. Я бы даже исполнение этих операций сделал бы с использованием Inline Assembler, поскольку аргументы часто будут повторяться, то их даже нет смысла возвращать в память, достаточно оставить в регистре проца. Все бы летало. Вот это была бы максимально возможная производительность - никаких циклов, условных переходов, вызовов функций и пр. Я еще думаю на тем, чтобы такое реализовать потом в обычной DLL, прилинкованной к CLR-сборке. Нужно будет только разобраться с импортом в sql clr-сборок с unmanaged кодом. ИзопропилandreybsВыделил 4 типа данных T, для каждого из которых применил подобную модель особого смысла в выделении типа D - не вижу. Каковы отношения между четырьмя типами T и C? Это одно и тоже, только разных типов. Правильнее будет сказать так: есть C1, C2, C3, C4. Объекты C1 содержат объекты C2, С3, С4, C2 содержат С3 и т.д. - это вертикальные связи. Есть еще горизонтальные связи типа объекты C3 связаны друг с другом через объекты C4. Короче, имеем некого рода сеть. D выделено исключительно для удобства. Эта структура содержит исходные данные объекта в БД. Структуру просто передавать по ссылке при импорте-экспорте данных. ИзопропилandreybsВсего одновременно живет до 1000 объектов (пока, в перспективе до 10000). 10000 - это очень мало. Да, не много. правда это на одну сессию. Ну, допустим будет 20 сессий, т.е. 200тыс элементов будут жить одновременно. НО! Примерно каждую секунду после окончания очередной итерации вычислений они будут полностью пересобираться на основе данных в БД, т.е. старые объекты будут отчуждаться, а новые будут создаваться на основе импортированных данных из БД. Я ожидаю достаточно интенсивную работу с памятью. ИзопропилandreybsВсе управление классами делается на базе внешнего статического класса (экономим на таблице методов в каждом классе). ничего не экономим - все экземпляры класса используют одну общую таблицу методов Возможно, тут я не разобрался пока. Мне казалось, что чем больше методов содержит класс, тем больше ссылок на них он должен содержать. Если этот класс копируется много раз в памяти, то вынос методов в отдельный статический класс позволит сэкономить на этих ссылках. Ну, как минимум, код стал на порядок читабельнее и масштабируеме при добавлении в алгоритм новых возможностей вычислений. Изопропилandreybs1. Нужно ли ставить Parent=null, чтобы разорвать сильные связи объектов и облегчить работу сборщика мусора. облегчить таким способом нельзя. Если на экземпляр класса в программе нет никаких ссылок - мусоросборщика не волнует, на кого ссылается этот экземпляр. Рихтера почитайте. Это хорошо, т.к. эти ссылки у меня readonly... :) Изопропилandreybs2. Нужно ли ставить Links.Capacity=0 после очистки массива, чтобы высвободить память для повторного использования новым объектом. нет, не нужно. Capacity влияет только на начальное выделение памяти для списка Ясно. Жаль, я надеялся влиять таким образом на очистку памяти до прихода мусорщика. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 10:43 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsНо хотел бы сделать это на С++. Но собрать сборку, которую схавает SQL пока не получилось. и не получится. MSSQL схавает c++ только сборку safe или pure.Смешаную - никак. А по возможностям в этом случае не будет разницы между managed c++ и c# А вообще-то c# поддерживает работу с неуправляемыми указателями Да, знаю, в области unmanaged. Я пока не разбирался с деталями импорта таких сборок, знаю только что "в лоб" они не импортируются в sql. Он ругается, что нужны расширенные права для владельца сборки и еще что-то там... Наверное, это решаемо, просто пока не добрался до этого. Сначала нужно будет разобраться с использованием памяти. Если сборка мусора при интенсивной работе с памятью будет снижать производительность, то C# не спасет даже указатели в области unmanaged, т.к. указатели нужно хранить в отдельном массиве, а это еще большие расходы памяти (если хранить указатель на каждый аргумент, как я писал выше). ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 10:53 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsОн ругается, что нужны расширенные права для владельца сборки и еще что-то там. Ну так и дайте эти расширенные права. У меня вовсю работает CLR для обработки изображений в БД. Без unsafe декларации она тоже не работает. Что ее бояться то ? (если надо ) ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 11:02 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsЯсно. Жаль, я надеялся влиять таким образом на очистку памяти до прихода мусорщика. мусоросборщик не так страшен. andreybsПримерно каждую секунду после окончания очередной итерации вычислений они будут полностью пересобираться на основе данных в БД, т.е. старые объекты будут отчуждаться, а новые будут создаваться на основе импортированных данных из БД. для мусоросборщика это очень хорошая среда ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 11:17 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsто C# не спасет даже указатели в области unmanaged, т.к. указатели нужно хранить в отдельном массиве никаких лишних массивов память под свою неуправляемую кучу попросить у операционной системы(Marshal.AllocHGlobal например) указатели неплохо хранятся в unsafe struct как в типизированом, так и в нетипизированом виде (void*) может потребоваться хранение в виде ulong(с приведением к void* или к чему надо и обратно) Код: c# 1. 2. 3. 4. 5. 6. 7.
andreybsони будут полностью пересобираться на основе данных в БД, т.е. старые объекты будут отчуждаться замечательно - можно иметь примитивный аллокатор и грохать всё ненужное простым вызовом Marshal.FreeHGlobal P.S. Надеюсь, под 64 бита хозяйство? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 11:44 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилandreybsто C# не спасет даже указатели в области unmanaged, т.к. указатели нужно хранить в отдельном массиве никаких лишних массивов память под свою неуправляемую кучу попросить у операционной системы(Marshal.AllocHGlobal например) указатели неплохо хранятся в unsafe struct как в типизированом, так и в нетипизированом виде (void*) может потребоваться хранение в виде ulong(с приведением к void* или к чему надо и обратно) Код: c# 1. 2. 3. 4. 5. 6. 7.
andreybsони будут полностью пересобираться на основе данных в БД, т.е. старые объекты будут отчуждаться замечательно - можно иметь примитивный аллокатор и грохать всё ненужное простым вызовом Marshal.FreeHGlobal Интересный способ, буду иметь ввиду. Один только вопрос - к чему прикрутить "деаллокатор"? Ведь деструкторы в C# не принято использовать, чтобы не замедлять мусорщика. Или все таки сделать один деструктор только для управляющего класса, объекты которого не пересоздаются все время? ИзопропилP.S. Надеюсь, под 64 бита хозяйство? Конечно... :) ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 11:56 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Что ж делается-то на свете? Что ж так плохо то все? Автор, может тебе какую-то задачу попроще взять для начала? А то класс от объекта не отличаем, а уже сразу ESP для mssql писать беремся? Ты возьми хоть на голом шарпе напиши сначала все, данные хоть из файла, хоть константами в программу вбей, отладь, потом уже в сервер суй. Оно может и без сервера тебя утроит. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 12:06 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsВедь деструкторы в C# не принято использовать, чтобы не замедлять мусорщика. никаких деструкторов и финализаторов в этой задаче не нужно! чистые голые структуры. деаллокатор относится к собственному менеджеру памяти. если нужно грохнуть всё - достаточно грохнуть весь пул (Marshal.FreeHGlobal) Итого - 1)прежде чем погружаться в эту трясину - Рихтера внимательно почитай и усвой 2)этим советом MasterZivна голом шарпе напиши сначала все воспользуйся, 10000*20 - не так много памяти занимает, а главное - не начинай преждевременную оптимизацию ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 12:15 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
MasterZivЧто ж делается-то на свете? Что ж так плохо то все? Автор, может тебе какую-то задачу попроще взять для начала? А то класс от объекта не отличаем, а уже сразу ESP для mssql писать беремся? Ты возьми хоть на голом шарпе напиши сначала все, данные хоть из файла, хоть константами в программу вбей, отладь, потом уже в сервер суй. Оно может и без сервера тебя утроит. Если вам что не понятно, спрашивайте, я поясню... А истерики и наезды нам точно не помогут. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 16:07 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилэтим советом MasterZivна голом шарпе напиши сначала все воспользуйся, 10000*20 - не так много памяти занимает, а главное - не начинай преждевременную оптимизацию Я уже сделал это. Все работает достаточно быстро. Сейчас я рассматриваю варианты оптимизации с использованием unsafe кода. Поскольку с C# работаю впервые, то его нюансы работы с памятью мною пока не освоены. У меня вопрос немного в сторону от темы - можно как-то обратиться по индексу (не ключу) к элементам словаря Dictionary? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 16:23 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsможно как-то обратиться по индексу (не ключу) к элементам словаря Dictionary? Код: c# 1.
это точно то что требуется? Может просто перебрать словарь как IEnumerable<T> нужно без всяких индексов? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 17:39 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилandreybsможно как-то обратиться по индексу (не ключу) к элементам словаря Dictionary? Код: c# 1.
это точно то что требуется? Может просто перебрать словарь как IEnumerable<T> нужно без всяких индексов? Да, это то что нужно. Но такого метода не существует. Почему не годится перебор - потому что во время вычислений нужно попеременно осуществлять перебор то в одном, то в другом направлении. Для максимально быстрой работы реализовать это можно только через прямой индекс (порядковый номер) и for и ни в коем случае не через сортировку и feach. При этом в момент генерации структуры для вычислений активно используется поиск по ключу, поэтому в кое-где приходится использовать словарь. В идеале нужен массив, удовлетворяющий следующим критериям: - динамическая структура (только добавление объектов) - поиск по ключу сложности О(1) (в качестве ключа используется одно из свойств объекта) - поиск по индексу сложности О(1) (в качестве индекса используется порядковый номер при добавлении в массив) К сожалению, не нашел таких массивов, поэтому где-то использую List<T>, а где-то Dictionary<T>. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 18:18 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
И еще вопрос по поводу затрат на упаковку/распаковку обращение по ссылкам. Что из этого будет менее затратным при многократном вызове: Вариант 1: for( int i=0; i<20; i++) ObjectA[1].Data.Value += ObjectB[i].Data.Value * ObjectC[i].Data.Value; Вариант 2 Double x; for( int i=0; i<20; i++) x += ObjectB[i].Data.Value * ObjectC[i].Data.Value; ObjectA[1].Data.Value = x; В варианте 1 вроде не должно быть упаковки/распаковки, т.к. значения прямо из кучи должны писаться в регистры CPU для вычисления, но мало ли... Зато много двойных переходов по ссылкам объект.объект.значение. В варианте 2 здесь должна быть распаковка при каждом "+=", но всего одна упаковка в самом конце. Какова цена обращения по ссылке по сравнению с распаковкой? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 19:10 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs Что из этого будет менее затратным при многократном вызове: ловля блох. это не оптимизация. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 19:18 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
beg-in-erandreybs Что из этого будет менее затратным при многократном вызове: ловля блох. это не оптимизация. При вызове 1000 или даже 10тыс раз - да. А при вызове 10млн или 100млн раз это ооочень заметно. Там даже лишний if заметен. не нужно недооценивать то, с чем не сталкивались. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 21:21 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs Там даже лишний if заметен. не нужно недооценивать то, с чем не сталкивались. я же не предложил избавится от цикла for и заменить его на 20 строк вида Код: c# 1.
, хотя это реально экономит время. практика оптимизации показывает, что игрища с языком толком скорости особо не дают. есть какой то прирост, но он даётся такой высокой ценой, что забиваешь на это. С++ быстрей шарпа где то раза в 2. и кстати 32 битные приложения могут работать заметно быстрее 64 битных. не зная , что там у тебя за расчёт но моя практика оптимизации математических задач говорит, что основное усилие надо приложить на оптимизацию самого алгоритма. если его тряхнуть скорость может вырасти качественно. ну и разумеется старатся отказываться от тормознутых Ienumerable в пользу чистых массивов. в любом случае каждая задача оптимизации сугубо индивидуальная. и все рассуждения - гадания на кофейной гуще. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 21:37 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
beg-in-erне зная , что там у тебя за расчёт топикстартер, не темни, выдай начальную задачу. И про освоение инструмента не забывай ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 21:45 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилbeg-in-erне зная , что там у тебя за расчёт топикстартер, не темни, выдай начальную задачу. И про освоение инструмента не забывай Изначальная задача - реализация нейросети прямого распространения с обучением методом обратного распространения ошибки. Нейросеть произвольного размера, т.е. с любым кол-вом входов, выходов, слоев, синапсов. Это что-то меняет? :) ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 21:53 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
beg-in-erне зная , что там у тебя за расчёт но моя практика оптимизации математических задач говорит, что основное усилие надо приложить на оптимизацию самого алгоритма. если его тряхнуть скорость может вырасти качественно. ну и разумеется старатся отказываться от тормознутых Ienumerable в пользу чистых массивов. "Чистые" массивы это Array[]? Или ты вообще про С++ говоришь? Если первое, то я понимаю, что нужно их использовать, но не получается, т.к. не знаю заранее их размера. Я на эту тему уже извелся... :( У меня два варианта: 1. Загрузить все данные из БД в большие массивы, а затем их раскладывать по маленьким массивам Array[]. Минус в том, что при регистрации связей между объектами придется делать многократный фулскан по большим массивам, выбирая связи, относящиеся к конкретному объекту. 2. Обрабатывать считанные данные из БД построчно, раскладывая их по динамическим массивам List<T>. Минус в том, что приходится использовать динамические массивы, а не "чистые". И еще минус в том, что выделение памяти пообъектно должно работать медленнее, чем выделение памяти для всего массива сразу. Сейчас я обдумываю третий вариант - сначала загрузить из БД статистику объектов (кого есть в каком кол-ве с каким кол-вом связей). Затем создать структуру в программе. Затем заполнить ее данными из второго обращения в БД. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 22:07 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsЭто что-то меняет? :) ну как бы да. причём тут БД? мну кажется ошибка где то тут, и оптимизировать надо начиная с этого места. чистый массив это типа int[] у массива есть свойство Resize. размер всегда можно поменять как в С. автор Минус в том, что при регистрации связей между объектами придется делать многократный фулскан по большим массивам, выбирая связи, относящиеся к конкретному объекту. ну эта работа для словаря. правда он довольно прожорлив по памяти. им можно попользоваться для установки связей и удалить. не скажу что задача плёвая, но ничего особого сложного из себя , на первый взгляд не предствляет. это же не NP полная задача. во что ты с ней дальше творишь... ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 22:17 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
beg-in-erС++ быстрей шарпа где то раза в 2. и кстати 32 битные приложения могут работать заметно быстрее 64 битных. Раз уж подняли вопрос про С++ снова, давайте его добьем... Открываем VS2012, создаем проект Visual C++ / CLR / библиотека классов. Заходим в "Свойства проекта" / "Свойства конфигурации" / "Поддержка общеязыковой среды CLR" выбираем "CLR-поддержка чистого MSIL (/clr:pure)". Компилим, импортируем в MSSQL2008. CREATE ASSEMBLY for assembly 'TestCPP' failed because the assembly is built for an unsupported version of the CLR runtime. Далее меняем на "CLR-поддержка безопасного MSIL (/clr:safe)". CREATE ASSEMBLY for assembly 'TestCPP' failed because the assembly is built for an unsupported version of the CLR runtime. "Поддержка CLR-среды (/clr)" CREATE ASSEMBLY for assembly 'TestCPP' failed because assembly 'TestCPP' is malformed or not a pure .NET assembly. Непроверяемый заголовок PE/собственная заглушка. Брехня. Собрано на базе .Net 2.0. Должно подходить для MSSQL2008. Короче, не работает. Ваши предложения, по настройке проекта? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 22:27 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
beg-in-erandreybsЭто что-то меняет? :) ну как бы да. причём тут БД? мну кажется ошибка где то тут, и оптимизировать надо начиная с этого места. Ну нейросеть то не в воздухе висит, ей данные нужны, а они подготавливаются в БД. Таблицы с миллионами записей... БД в самый раз. beg-in-erчистый массив это типа int[] у массива есть свойство Resize. размер всегда можно поменять как в С. Ну здрасьте. Цитирую документацию - этот метод создает новый массив и копирует его на место старого. Операция сложности О(n). Для сравнения List<T>.Add сложности O(1). Ну и где тут преимущество на массиве, скажем, из 1000 элементов? beg-in-erавтор Минус в том, что при регистрации связей между объектами придется делать многократный фулскан по большим массивам, выбирая связи, относящиеся к конкретному объекту. ну эта работа для словаря. правда он довольно прожорлив по памяти. им можно попользоваться для установки связей и удалить. Супер! Его я использую в некоторых случаях. Но не нравится он мне, т.к. не умеет извлекать элемент по индексу. Не нравится. :) beg-in-erне скажу что задача плёвая, но ничего особого сложного из себя , на первый взгляд не предствляет. это же не NP полная задача. во что ты с ней дальше творишь... А дальше это будет кластер нейросетей. Поверь, я готов каждую запятую учесть, чтобы не потерять в производительности. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 22:33 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsbeg-in-erне зная , что там у тебя за расчёт но моя практика оптимизации математических задач говорит, что основное усилие надо приложить на оптимизацию самого алгоритма. если его тряхнуть скорость может вырасти качественно. ну и разумеется старатся отказываться от тормознутых Ienumerable в пользу чистых массивов. "Чистые" массивы это Array[]? Или ты вообще про С++ говоришь? Если первое, то я понимаю, что нужно их использовать, но не получается, т.к. не знаю заранее их размера. Я на эту тему уже извелся... :( У меня два варианта: 1. Загрузить все данные из БД в большие массивы, а затем их раскладывать по маленьким массивам Array[]. Минус в том, что при регистрации связей между объектами придется делать многократный фулскан по большим массивам, выбирая связи, относящиеся к конкретному объекту. 2. Обрабатывать считанные данные из БД построчно, раскладывая их по динамическим массивам List<T>. Минус в том, что приходится использовать динамические массивы, а не "чистые". И еще минус в том, что выделение памяти пообъектно должно работать медленнее, чем выделение памяти для всего массива сразу. Сейчас я обдумываю третий вариант - сначала загрузить из БД статистику объектов (кого есть в каком кол-ве с каким кол-вом связей). Затем создать структуру в программе. Затем заполнить ее данными из второго обращения в БД. ArraySegment . Если нужно быстродействие,то зачем какие-то бубны со сборками в sql server? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 22:42 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsКороче, не работает. Ваши предложения, по настройке проекта? блд, русским языком говорил - /clr:safe или /clr:pure - только возможкности ничем не будкут отличасться от c# ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 22:51 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsКороче, не работает. Ваши предложения, по настройке проекта? блд, русским языком говорил - /clr:safe или /clr:pure Да блин, а это что? 38 попугаев?? andreybsДалее меняем на "CLR-поддержка безопасного MSIL (/clr:safe)". CREATE ASSEMBLY for assembly 'TestCPP' failed because the assembly is built for an unsupported version of the CLR runtime. Строка компоновщика: /Yu"stdafx.h" /GS /analyze- /W3 /Zc:wchar_t /Zi /Od /Fd"Debug\vc110.pdb" /fp:precise /D "WIN32" /D "_DEBUG" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /errorReport:prompt /WX- /Zc:forScope /Oy- /clr:pure /FU"C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll" /FU"C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll" /FU"C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll" /FU"C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll" /MDd /Fa"Debug\" /EHa /nologo /Fo"Debug\" /Fp"Debug\TestCPP.pch" Только толку от этого нет. Работает только через Platform Invoke. А это черте-что цеплять DLL на C#, которая цепляет другую DLL на С++. Как этого монстра дебагить ваще не ясно. Изопропил- только возможкности ничем не будкут отличасться от c# Вот именно. CLR он и в африке CLR. Тогда что говорить о том, что код С++ в два раза быстрее? ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 23:05 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
SeVaЕсли нужно быстродействие,то зачем какие-то бубны со сборками в sql server? Ваши варианты? Пользовательское приложение? Я пока не придумал, как взаимодействовать с ним из БД. Предполагается, что источник вызова на вычисление - ХП в БД. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 23:12 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsКак этого монстра дебагить ваще не ясно. с головы на ноги поставить - клиент на c#, сервер без всякого clr для управления - WCF захостить ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 23:14 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsПредполагается, что источник вызова на вычисление - ХП в БД. попробуйте вызвать ХП из клиентского приложения. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 23:15 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsПредполагается, что источник вызова на вычисление - ХП в БД. попробуйте вызвать ХП из клиентского приложения. Это кажется более разумным, чем WCF. Как-то не верится, что HTTP-шная прослойка (мы же о веб-сервисах горовим, если я не ошибаюсь) обеспечит быстрое взаимодействие со сборкой. Возможно, перенос управления в модуль C++ (клиентское приложение) будет самым производительным и верным решением. Попробую реализовать такой вариант, посмотрим, как это повлияет на производительность. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 23:24 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsWCF это для управления, а не для вычислений - вроде с управлением траблы были ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 23:25 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs Ну здрасьте. Цитирую документацию - этот метод создает новый массив и копирует его на место старого. Операция сложности О(n). Для сравнения List<T>.Add сложности O(1). Ну и где тут преимущество на массиве, скажем, из 1000 элементов? при построении в памяти естесно лучше использовать типа стека, а после перехерачивать в массив. ToArray() Супер! Его я использую в некоторых случаях. Но не нравится он мне, т.к. не умеет извлекать элемент по индексу. Не нравится. :) так годиться? Dictionary<int, int> DD; var x= DD.ElementAt(1); А дальше это будет кластер нейросетей. Поверь, я готов каждую запятую учесть, чтобы не потерять в производительности. ещё раз. улучшив алгоритм можно качественно улучшить скорость. гонка за запятую даст слишком мало прироста. уж что что а прирост может дать совершенно другие вещи. как то другой проц ( типа extream edition ) или GPU, генерация кода под специфику задачи, отказ от рекурсий, отказ от LINQ..... - это много эффективнее , чем ловля блох. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 23:50 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
скорость зависит от цены задачи. может оказаться , что проще решать не на серваке с его "распаралелеными задачами" а на выделенной тачке Core i7 ExEdition. проще, понятнее и дешевле. ... |
|||
:
Нравится:
Не нравится:
|
|||
30.07.2013, 23:54 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsWCF это для управления, а не для вычислений - вроде с управлением траблы были В этом плане проще тогда создать интерфейсную табличку в БД и постоянно "слушать" ее. Тот же WCF, только без HTTP. Я придумал, как организовать взаимодействие - консольная программа, звпускаемая "on demand" через shell или джоб со стороны sql-сервера. Ограничение только одно - она не должна запускаться слишком часто, т.к. процессы запуска приложения в Windows несут большие временные затраты. Это похоже на механизм работы агента репликации, который так же запускается и висит в памяти до тех пор, пока джоб не остановят. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2013, 08:06 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
beg-in-erпри построении в памяти естесно лучше использовать типа стека, а после перехерачивать в массив. ToArray() Копирование из массива в массив (в моем случае копирование таких массивов тысячи) слишком затратно по операциям. Нужно сразу писать в рабочий массив. beg-in-erещё раз. улучшив алгоритм можно качественно улучшить скорость. гонка за запятую даст слишком мало прироста. уж что что а прирост может дать совершенно другие вещи. как то другой проц ( типа extream edition ) или GPU, генерация кода под специфику задачи, отказ от рекурсий, отказ от LINQ..... - это много эффективнее , чем ловля блох. Согласен. Поэтому решу задачу на С++ в виде отдельного приложения, а там посмотрим. Есть у меня пара идей, ка на инлайн ассемблере все в разы ускорить... ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2013, 08:15 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Assembler - это опять преждевременная оптимизация ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2013, 08:19 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилAssembler - это опять преждевременная оптимизация Ладно, ладно, это далекая перспектива, но вполне реальная. О ней позже, сначала С++. Давно писал кучу приложений на С++ Builder по работе с БД, а на VC++ такое ПО не писал - что то немного застрял разбираясь, как к проекту консольного приложения библиотеки adodb подцепить, чтобы нативный доступ к SQL-сервер организовать... ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2013, 09:12 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsкак к проекту консольного приложения библиотеки adodb подцепить Код: c# 1.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms675103(v=vs.85).aspx ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2013, 09:19 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилandreybsкак к проекту консольного приложения библиотеки adodb подцепить Код: c# 1.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms675103(v=vs.85).aspx Вот спасибо! Как раз включил комп, ща закодим... Я сделал вчера замеры вычислений простенькой нейросети в сборке на С#, реализую аналогичный алгоритм на С++ и сравню результаты производительности по той же сети. Самому интересно - одно дело статьи читать, а другое дело в живую убедиться. ... |
|||
:
Нравится:
Не нравится:
|
|||
31.07.2013, 10:26 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Наконец то добрался до своей задачи, сейчас пишу компактную библиотеку оберточных классов для ADO DB под мою задачу. Есть вопрос... Для сохранения высокой производительности нужно максимально эффективно организовать работу с БД. Для этого нужно избегать многократной перекомпиляции одинаковых запросов. Для этого запросы нужно писать с использованием параметров. Все работает отлично, но один момент мне не нравится... Есть маленькое неудобство, которое заключается в том, что при создании параметра приходится указывать тип DataTypeEnum, значение _variant_t и размер long. Очевидно, что в большинстве случаев можно на основании типа значения _variant_t.vt извлечь и тип значения и его размер, сократив таким образом количество входных параметров на два. Мне не удается найти описание типа VARTYPE. Например, здесь есть только часть возможных значений Вообще, какие существуют УНИВЕРСАЛЬНЫЕ (т.е. не зависящие от значения _variant_t) способы извлечения DataTypeEnum и размера данных из переменной _variant_t? ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2013, 12:20 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs, ADO DB - это и так обёртка над OLEDB для скриптовых языков - отсюда и VARIANT вместо VARIANT можно использовать CComVariant ( это обёртка над VARIANT ) полное описание в wtypes.h и http://msdn.microsoft.com/en-us/library/windows/desktop/ms221170(v=vs.85).aspx если не хочется возиться с OLE - ODBC используй. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2013, 13:15 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилandreybs, ADO DB - это и так обёртка над OLEDB для скриптовых языков - отсюда и VARIANT вместо VARIANT можно использовать CComVariant ( это обёртка над VARIANT ) полное описание в wtypes.h и http://msdn.microsoft.com/en-us/library/windows/desktop/ms221170(v=vs.85).aspx если не хочется возиться с OLE - ODBC используй. Именно этот кодификатор мне и нужен, спасибо! Я сделал обертку только части функций ado, сгруппировав их конкретно под мою задачу. Максимально компактно и без лишних наворотов, исключительно для удобства использования и читабельности кода. А по поводу odbc не уверен, что он подойдет. У меня используется много специфики от sql-сервера - работа с временными таблицами, табличными функциями, прямая-обратная передача параметров и пр. Не факт, что это будет поддерживаться в odbc. Так что я повожусь с ole... :) Тем более, что уже библиотечку написал, оттестировал и подготовил к работе. ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2013, 20:56 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsУ меня используется много специфики от sql-сервера тогда OLEDB лучше чем ADODB, хотя на старте усилий больше потребует ... |
|||
:
Нравится:
Не нравится:
|
|||
03.08.2013, 21:42 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsУ меня используется много специфики от sql-сервера тогда OLEDB лучше чем ADODB, хотя на старте усилий больше потребует А чем принципиально лучше? Производительность? Если да, то можно ли как-то оценить ожидаемый прирост производительности до того, как углубляться в OLE? Со временем могу свою обертку переделать на OLE вместо ADO. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2013, 17:45 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsА чем принципиально лучше? вроде ж табличные параметры передавать хотел - http://msdn.microsoft.com/ru-ru/library/ff877933.aspx ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2013, 18:42 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsА чем принципиально лучше? вроде ж табличные параметры передавать хотел - http://msdn.microsoft.com/ru-ru/library/ff877933.aspx Я говорил о табличных функциях и возвращаемых параметрах, но не важно... Я как-то не думал, что мне потребуется работать с табличными переменными, хотя эта идея тоже хорошая. Буду иметь ввиду, что это через OLE DB можно реализовать. Спасибо за инфу! ... |
|||
:
Нравится:
Не нравится:
|
|||
04.08.2013, 21:03 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Хотел уточнить по поводу хранения кода методов классов в памяти... Правильно ли я понимаю, что: 1. объект класса хранит лишь таблицу указателей на экземпляры методов класса 2. все экземпляры методов всех классов хранятся в одной и той же области памяти программы 3. для всех объектов одного и того же класса используются одни и те же экземпляры методов (т.е. число экземпляров методов классов не увеличивается с увеличением числа объектов классов) 4. размер памяти, выделяемой на хранение объекта класса, увеличивается на N байт при добавлении в класс нестатического метода, где N-размер ссылки в текущем адресном пространстве памяти (обычно 4 байта, для x32) ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2013, 09:05 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs, 1) да, адрес таблицы 2) все экземпляры методов - что имеется ввиду? Код общий, хранится в сегменте кода 3) да, но забудьте про "экземпляры методов", в с++/c# все экземпляры класса разделяют код 4) нет, увеличивается только размер таблицы методов, которая одна на класс. P.S. детали(ка-то метаданные, виртуальные методы, отличия c# от с++) опущены ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2013, 10:57 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилandreybs, 1) да, адрес таблицы 2) все экземпляры методов - что имеется ввиду? Код общий, хранится в сегменте кода 3) да, но забудьте про "экземпляры методов", в с++/c# все экземпляры класса разделяют код 4) нет, увеличивается только размер таблицы методов, которая одна на класс. P.S. детали(ка-то метаданные, виртуальные методы, отличия c# от с++) опущены Ясно, спасибо. А конструкторы тоже хранятся в памяти, как обычные методы в общем сегменте кода? Вопрос возник в связи с тем, что конструкторы могут быть включены в состав структуру (struct), у которой не должно быть таблицы методов в отличие от классов (class). ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2013, 12:16 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsА конструкторы тоже хранятся в памяти, как обычные методы в общем сегменте кода? да, хранятся так же. "Лишний" указатель - вряд ли является узким местом в данном проекте. память, выделяемая C-шным malloc - тоже имеет накладные расходы - на выравнивание данных, на хранение длины выделенного блока. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2013, 12:49 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsА конструкторы тоже хранятся в памяти, как обычные методы в общем сегменте кода? да, хранятся так же. "Лишний" указатель - вряд ли является узким местом в данном проекте. память, выделяемая C-шным malloc - тоже имеет накладные расходы - на выравнивание данных, на хранение длины выделенного блока. Да, с malloc есть проблема. На основании этой статьи я решил построить все на базе динамического массива (std::vector), содержащего структуры (включая вложенные динамические массивы ссылок) с описанием элементов системы. В моем случае интересует максимально быстрый последовательный доступ к элементам массивов и добавление элементов в конец массивов. Для уменьшения фрагментированности памяти я планирую предварительно отсортировать средствами СУБД импортируемые из БД данные со структурой системы. Как-то так будем бороться с недостатками malloc... ... |
|||
:
Нравится:
Не нравится:
|
|||
05.08.2013, 17:34 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Скорость ADO не радует при возврате блока данных в sql-сервер. Судя по профайлеру, если передавать строки через объект рекордсета, то данные передаются с помощью курсора. Если передавать напрямую через команду insert с параметрами, то получается быстрее, но все равно не то. Нужен либо BULK Copy, либо возвращаемая табличная переменная. Решил таки использовать шаблоны OLEDB (sqloledb + atldbcli) вместо ADO. Чертов OLEDB задрал уже... Мало того, что в документации msdn нет нормальных примеров, так баг на баге сидит. Вот, сейчас борюсь с некорректной работой удаления CDynamicStringAccessor без параметров . И оказывается, это далеко не единственный косяк в библиотеке. Я вот чего не пойму - я ставил vs2012 ultimate, на нее даже какие-то апдейты накатились. Но баги с OLEDB остались, хотя о них известно давно (судя по статьям). Может нужно какой фикс на vs2012 скачать, не в курсе? И еще вопрос по специфике использования oledb с mssql. Почему то мне не удается выполнить неподготовленную команду. CCommand.Open выдает ошибку "команда не подготовлена". Если команду подготовить, то в профайлере видно "exec sp_prepexec ... exec sp_unprepare", а я хочу "exec sp_executesql", который в моем случае будет быстрее. ADO выполнял команды без prepare именно через sp_executesql. Непонятно, как добиться этого же с помощью CCommend. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.08.2013, 12:25 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs, если борьба за последние микросекунды - лучше использовать хранимые процедуры ... |
|||
:
Нравится:
Не нравится:
|
|||
11.08.2013, 15:24 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Изопропилandreybs, если борьба за последние микросекунды - лучше использовать хранимые процедуры Это не поможет. Объясню. Потери возникают в момент возврата рассчитанных данных в sql-сервер. Так уж получается, что для серьезной задачи приходится возвращать порядка 1000 строк за каждый такт вычислений. А при той скорости вычислений, которой мне удалось добиться (на тестовой задаче: ~250тыс вычислений в секунду, ~10тыс вычислений на такт, ~25тактов/сек) эта чертова вставка жрет слишком много времени. Так вот, сейчас происходит вставка данных в лоб при помощи приготовленной параметризированной команды insert, которая вызывается 1000 раз в каждый такт, т.е. 25тыс вставок в секунду. Оптимизатору sql будет все равно - будет ли делать вставку команда insert или хранимая процедура с параметрами, главный минус - каждая вставка порождает одну транзакцию, которая фиксируется в журнале транзакций. Я хочу использовать BULK INSERT (интерфейс FastLoad из OLEDB), что должно либо сильно ускорить вставку, т.к. сам механизм BULK INSERT работает на физическом уровне и каждая вставка выполняется за рамкой транзакции. Думал это реализовать через OLE DB, но серьезно увяз в нюансах его работы. Сейчас попробую еще одну идею - скрестить ADO и шаблоны OLEDB. В некоторых классах ADO есть выход на DataSource. Можно попробовать за него зацепиться и создать класс расширения ADOBulkInsert. Тогда сохранится удобство обертки ADO (на ней все прекрасно работает) и добавится новая возможность. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.08.2013, 18:10 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsЭто не поможет. а к чему тогда слёзы по sp_prepexec ? andreybsЯ хочу использовать BULK INSERT правильно. А закончится заменой СУБД ... |
|||
:
Нравится:
Не нравится:
|
|||
11.08.2013, 18:20 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
ИзопропилandreybsЭто не поможет. а к чему тогда слёзы по sp_prepexec ? andreybsЯ хочу использовать BULK INSERT правильно. А закончится заменой СУБД sp_prepexec нужен не всегда. Он нужен только для повторяющихся команд. Для одиночных команд select лучше использовать sp_executesql. Как управлять этим из ADO - мне понятно, но повторить это в OLEDB у меня не получилось, примеров я не нашел, а пробовать готовые библиотеки и копаться в их исходниках просто нет не времени ни желания. Заменой СУБД не закончится - в ней достаточно сложная обработка больших массивов статистических данных. Реализовать такое в программе мне не под силу в разумные сроки. Так что буду добивать вариант выноса вычислений за пределы СУБД. Ведь все получилось, остался один маленький шажок с BULK INSERT через OLEDB... ... |
|||
:
Нравится:
Не нравится:
|
|||
11.08.2013, 18:51 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Уф, ну и намучился я с этим капризным OLE DB. Короче, может кому понадобится, вот кусок кода на C++, как подключиться к открытому коннекту ADO Connection и получить доступ к интерфейсу OLE IRowsetFastLoad (он же BULK INSERT) для дальнейшей массовой вставки данных в таблицу... Это как раз то, что мне не хватало в ADO. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42.
Если кому нужно, то от сюда можно дернуть исходники по самой вставке данных ... |
|||
:
Нравится:
Не нравится:
|
|||
12.08.2013, 01:10 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Обрабатывая логику программы, внезапно обнаружил, что на каждую вставку pFastLoad->InsertRow(..) в sql-сервер уходит команда BULK INSERT. Вроде не должно быть такого - должен блоками вставлять: (SSPROP_FASTLOADOPTIONS, L"ROWS_PER_BATCH=10000"). Может причина в pFastLoad->Commit(FALSE), который идет сразу за pFastLoad->InsertRow(..)? В примерах именно так написано, но может Commit(FALSE) не надо трогать до окончания вставки, а в конце сразу сделать Commit(TRUE)? ... |
|||
:
Нравится:
Не нравится:
|
|||
19.08.2013, 09:29 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsОбрабатывая логику программы, внезапно обнаружил, что на каждую вставку pFastLoad->InsertRow(..) в sql-сервер уходит команда BULK INSERT. Вроде не должно быть такого - должен блоками вставлять: (SSPROP_FASTLOADOPTIONS, L"ROWS_PER_BATCH=10000"). Может причина в pFastLoad->Commit(FALSE), который идет сразу за pFastLoad->InsertRow(..)? В примерах именно так написано, но может Commit(FALSE) не надо трогать до окончания вставки, а в конце сразу сделать Commit(TRUE)? Так и есть - Commit всегда вставляет в базу вне зависимости от принимаемого параметра. Нужно делать Commit(true) только в самом конце вставки. Сам спросил - сам ответил... :) ... |
|||
:
Нравится:
Не нравится:
|
|||
19.08.2013, 11:15 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
В итоге реализовал одну и туже задачу в трех средах. Произвел замеры скорости вычислений простенькой нейросети: результаты: (вычислений/сек) СУБД t-sql 540 exe C++ 48000 clr C# 72000 В общем, это какой-то провал.... C# почти в два раза быстрее. Я не понимаю, почему так получилось - алгоритмы одни и те же, реализация самих вычислений проста и одинаково реализована. Буду думать... ... |
|||
:
Нравится:
Не нравится:
|
|||
20.08.2013, 22:28 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsрезультаты: (вычислений/сек) СУБД t-sql 540 exe C++ 48000 clr C# 72000 В общем, это какой-то провал.... C# почти в два раза быстрее. Я не понимаю, почему так получилось - алгоритмы одни и те же, реализация самих вычислений проста и одинаково реализована. Буду думать... ну вот , оптимизация на лицо. скорость выросла в 100 раз. по сравнению с t-sql. а что до того, что якобы C# быстрее ...так это по тому например, что оптимизатор в С# очень неплохой. убери галочку оптимизировать код и сравни ))) тут надо сравнивать ассемблерный код. чудес не бывает. увы. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 09:44 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
beg-in-erandreybsрезультаты: (вычислений/сек) СУБД t-sql 540 exe C++ 48000 clr C# 72000 В общем, это какой-то провал.... C# почти в два раза быстрее. Я не понимаю, почему так получилось - алгоритмы одни и те же, реализация самих вычислений проста и одинаково реализована. Буду думать... ну вот , оптимизация на лицо. скорость выросла в 100 раз. по сравнению с t-sql. а что до того, что якобы C# быстрее ...так это по тому например, что оптимизатор в С# очень неплохой. убери галочку оптимизировать код и сравни ))) тут надо сравнивать ассемблерный код. чудес не бывает. увы. Ну, я не сомневался, что C# не плох, но везде пишут, что С++ быстрее раза в два... Я хочу докопаться до причины обратной зависимости в моем случае. Что-то тут явно не то... Сделал отдельную ветку по оптимизации C++ программы . Дальше для ускорения хочу попробовать использовать технологию C++ Accelerated Massive Parallelism для вычислений на базе процессора видеокарты. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 11:35 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsВ дотнетах два основных тормоза: 1. Контроль типов при преобразовании от базового класса к потомку. 2. Контроль границ массивов - основной тормоз. Есть ещё автоматическое управление памятью, но там не всё так однозначно. Делай выводы... ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 11:41 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
Алексей КandreybsВ дотнетах два основных тормоза: 1. Контроль типов при преобразовании от базового класса к потомку. 2. Контроль границ массивов - основной тормоз. Есть ещё автоматическое управление памятью, но там не всё так однозначно. Делай выводы... 1. учтено. в повторяющихся операциях исключено. 2. учтено. считывание границ один раз за цикл. Управление памятью в данном случае не влияет, т.к. замеры производим, когда все массивы уже заполнены. Еще одна фишка - вставил счетчики на базе статических внешних Stopwatch во внутренние функции в проге на C# и производительность упала в 10 раз!!! Надо искать другие варианты точного расчета времени выполнения. Буду экспериментировать... ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 14:19 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsБуду экспериментировать... Укорения в 100 раз мало? ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 14:22 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
beg-in-erandreybsБуду экспериментировать... Укорения в 100 раз мало? Мало. :) Я хочу добиться производительности на С++ в два раза выше, чем на С#, а после еще ускорить за счет параллелизма вычислений через GPU. ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 17:11 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybs, как только у Вас получится реализовать задуманное... и это протянет в продакшене хоть у одного кастомера месяцев шесть... отпишите сюда... ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 17:31 |
|
высокопроизводительная CLR-сборка с кодом на C++ для SQL Server
|
|||
---|---|---|---|
#18+
andreybsВ итоге реализовал одну и туже задачу в трех средах. Произвел замеры скорости вычислений простенькой нейросети: результаты: (вычислений/сек) СУБД t-sql 540 exe C++ 48000 clr C# 72000 В общем, это какой-то провал.... C# почти в два раза быстрее. Я не понимаю, почему так получилось - алгоритмы одни и те же, реализация самих вычислений проста и одинаково реализована. Буду думать... Причина тормознутости проги на C++ была в неверных настройках компилятора. На деле С++ получился в 14 (!!!) раз быстрее С#: 2142000 против 125000 вычислений/сек. Вот это дело! Теперь я не жалею, что перевел все на С++... ... |
|||
:
Нравится:
Не нравится:
|
|||
21.08.2013, 17:33 |
|
|
start [/forum/topic.php?all=1&fid=20&tid=1404184]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
37ms |
get topic data: |
14ms |
get forum data: |
3ms |
get page messages: |
110ms |
get tp. blocked users: |
2ms |
others: | 13ms |
total: | 211ms |
0 / 0 |