Камышев Александр

Пользователи
  • Публикации

    212
  • Зарегистрирован

  • Посещение

  • Days Won

    8

Камышев Александр last won the day on 14 ноября 2016

Камышев Александр had the most liked content!

О Камышев Александр

  • Активность Раздел Android
  • Звание
    Продвинутый пользователь
  • День рождения 02.12.1978

Информация

  • Пол
    Мужчина
  • Город
    Москва, Троицк

Посетители профиля

470 просмотров профиля
  1. Некорректно выразился, на андроид не работает связка FireDac + MySQL, т.к. используется libmysql.dll, с sqLite все вроде ок.
  2. мдя, чудес не бывает, в базе и близко нет 3к записей в секунду, из-за ошибки с флагом наложение данных и до записи доходит процентов 10-20, потому и ресурсов мало потребляет.
  3. статистика: запросов задач в сек. 3000 подтверждений в сек. 0 параметры файлов в сек. 0 запросов данных в сек. 0 запросов клиента в сек. 0 время запроса, мсек. 156 активных соединений с бд 10 из 10 запросов в бд в сек. 3000 размер очереди в бд 1365 из 5000 время запроса к бд, мсек. 31 устройства 2490 профили 139 задачи 51 файлов доступно 11 db_client 0 запросов в сек. 300 db_client 1 запросов в сек. 302 db_client 2 запросов в сек. 300 db_client 3 запросов в сек. 300 db_client 4 запросов в сек. 301 db_client 5 запросов в сек. 300 db_client 6 запросов в сек. 300 db_client 7 запросов в сек. 298 db_client 8 запросов в сек. 299 db_client 9 запросов в сек. 300
  4. При запросе оборудование сообщает серверу свои параметры, сервер записывает их в базу, всего три записи в три таблицы, два целых числа и одна строка плюс ключевые поля. Selectы сервер делает периодически, через 5 минут, обновление кэша. Практически идет только запись. На пакет http ответ уходит сразу, без подтверждения записи в бд. Если ждать подтверждение скорость резко падает, и больше 600-800 http запросов служба затыкается, краш где-то получается. Всего удалось получить больше 3000 тысяч запросов т.е. 3000 * 3 = 9к в секунду, движок СУБД при этом занимает 10-15% загрузки. MySql с максимальными настройками, измерял время потраченное на три запроса - поднималось в пике до 50мс. Десять коннектов держали по 300 таких пакетов запросов, т.е. среднее время должно было быть ~3 мс на запрос. Как-то не сходится... буду дальше копать
  5. В продолжение темы. С асинхронным режимом amAsync в FD все плохо, нет колбэков - полбеды, на 1200-1500 крашится все сразу, на нескольких сотнях запросов умирает медленно и мучительно. Завершение работы через раз с крашем. Режим amNonBlocking ненамного лучше, те же яйца только в профиль, годится только для клиентского интерфейса работы с БД. Перемудрили что-то разработчики там с потоками. Остался режим amBlocking + TTrhead. Класс для простоты общения со средом: //--------------------------------------------------------------------------- class TMyDBConnThread : public TThread { private: TInterlocked *Interlocked; TNotifyEvent FOnExecute; TNotifyEvent FOnReady; void __fastcall SyncReady(){ FOnReady(this); } protected: void __fastcall Execute(); public: __fastcall TMyDBConnThread(bool CreateSuspended); __property TNotifyEvent OnExecute = { read = FOnExecute, write = FOnExecute }; __property TNotifyEvent OnReady = { read = FOnReady, write = FOnReady }; TFDConnection *connection; TFDQuery *query; TSimpleEvent *event; int buzy; }; //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- void __fastcall TMyDBConnThread::Execute() { Interlocked = new TInterlocked; while ( !Terminated ) { event->WaitFor( INFINITE ); if ( Terminated ) break; Interlocked->Exchange( buzy, 1 ); FOnExecute(this); Interlocked->Exchange( buzy, 0 ); event->ResetEvent(); Synchronize( SyncReady ); } delete Interlocked; delete event; } //--------------------------------------------------------------------------- Вся работа с бд в FOnExecute и потокозащищенный колбэк FOnReady. Далее удивление: устойчивая работа, отсутствие ошибок, 9000+ запросов в БД в секунду и при этом 20-30% загрузки, в асинхронном режиме для сравнения 1500 запросов под 60%. Все зависит от степени кривизны рук, однако...
  6. это и есть трехзвенка, код из сервера приложений , про болезнь - тогда понятно, думал может я чего путаю. спс
  7. Windows, TFDConnection + TFDQuery, асинхронный режим запросов, 10 TFDQuery создаются динамически fconnection = new TFDConnection(NULL); fquery = new TFDQuery(NULL); fquery->Connection = fconnection; fquery->AfterOpen = AfterOpen; fquery->AfterExecute = AfterExecute; fquery->OnError = QueryError; Всего около 500 запросов в секунду, т.е. по 50 на каждый, после каждого запроса по AfterOpen и AfterExecute сразу следующий запрос из очереди. В случае QueryError - разрыв соединения и через паузу повтор. При тестировании была выявлена деградация количества записей в секунду, вплоть до полной остановки. Локализация показала, что при высокой нагрузке TFDQuery иногда не возвращает callback менее чем совсем, ни AfterExecute ни QueryError, в общем "друг, оставь покурить, а в ответ - тишина". При этом у TFDConnection State = csConnected и у TFDQuery State = dsInactive. Проблема была решена костылем с таймаутом, если за секунду нет ответа - уход в ошибку с разрывом соединения и повтором. Теперь вопрос, может я чего-то не знаю? где callback?
  8. Бывает Про директивы не знал, теперь буду в курсе, так изящнее, спасибо, но увы и ах: The memory allocation directives are meaningful only in a program. They should not be used in a library or a unit. т.е. в System.Classes.pas и в IdThread.pas вставлять нельзя, ибо should not be used in a library or a unit. Indy сама создает потоки в коде библиотеки IdCustomTCPServer.pas. и еще {$M 16384, 65535} - полагаю размеры указаны неверно, от 64К до 1М, возможно я ошибаюсь, вроде: гранулярность выделения адресного пространства равна 64 Кб, сдругой стороны из описания Default {$M 16384,1048576} В общем, все таки брутальный подход, только хардкор...
  9. результаты краш-теста - упал в "Недостаточно памяти" после 5770 запросов в секунду, как бы и ничего так С обращением к пулу - 3к и без задержек на доступ к критическим секциям 5к запросов с задержкой 200 мсек. - непринужденно, конечно после допила системного TThread, беда кстати была не в инди, а в теплом ламповом borland. тестировалось на ПК разработчика, сервер и эмулятор на localhost:
  10. Не думаю что сколько нибудь заметно, если брать http пакеты, ведь TIdHTTPServer наследник от TIdCustomTCPServer. Если пересылать бинарные массивы, без парсинга хедеров - возможно и будет небольшое увеличение. Был приятно удивлен, по всем ядрам ровная нагрузка.
  11. думаю эти два куска показывают основную обработку OnCommandGet, из хедера: typedef std::deque< strDBQueueMember* > db_queue_deque; db_queue_deque db_queue; TCriticalSection *cs_pool, *cs_queue, *cs_files; TInterlocked *Interlocked; 3600 это запрос без обращения к бд, только данные из пула с критическими секциями ну и вот это обязательно в System.Classes.pas в Embarcadero\Studio\17.0\source\rtl\common\ constructor TThread.Create(CreateSuspended: Boolean); -//- {$IF Defined(MSWINDOWS)} //#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 - это для информации //#define CREATE_SUSPENDED 0x00000004 - это для информации // заменить FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID); // на FHandle := BeginThread(nil, 65536, @ThreadProc, Pointer(Self), $00010004, FThreadID); System.Classes.pas добавить в проект. и будет вам счастье
  12. //--------------------------------------------------------------------------- void TdmSkyUpdate::PostCommand( strCommandData *cd ) { bool is_client = false; if ( !cd->req->AuthExists ) { cd->sx_auth = cd->req->RawHeaders->Values["X-SX-auth"]; if ( cd->sx_auth.IsEmpty() ) { cd->resp->ResponseNo = 401; return; } is_client = true; } if ( !is_client ) { strDeviceCmd dc; dc.cd = cd; cs_pool->Enter(); PostDevice( &dc ); cs_pool->Leave(); if ( !dc.db_queue.size() ) return; if ( !PushToDBQueue( &dc.db_queue ) ) { cd->resp->ResponseNo = 500; return; } } else { strClientCmd cc; cc.cd = cd; cs_pool->Enter(); PostClient( &cc ); cs_pool->Leave(); if ( !cc.db_queue.size() ) return; if ( !PushToDBQueue( &cc.db_queue ) ) { cd->resp->ResponseNo = 500; return; } if ( cc.file_data.data ) SaveTaskFile( &cc.file_data, cc.file_id ); } } //---------------------------------------------------------------------------
  13. //----------------------------------------------------------------------- void __fastcall TdmSkyUpdate::serverCommandGet(TIdContext *AContext, TIdHTTPRequestInfo *ARequestInfo, TIdHTTPResponseInfo *AResponseInfo) { strCommandData cd; #ifdef AUX_MODE #ifdef MY_DEBUG_MODE cd.log_queue.push_back( ARequestInfo->RawHTTPCommand ); // debug cd.log_queue.push_back( ARequestInfo->RawHeaders->Text ); // debug #endif MyTimer timer; timer.Start(); #endif if ( db_queue_size >= max_db_queue_size ) { AResponseInfo->ResponseNo = 503; #ifdef MY_DEBUG_MODE cd.log_queue.push_back( "Переполнение очереди в бд, ограничение " + (AnsiString)max_db_queue_size ); // debug PushToLogQueue( &cd.log_queue ); TIdNotify::NotifyMethod( OnLogQueue ); #endif return; } cd.req = ARequestInfo; cd.resp = AResponseInfo; cd.user = cd.req->AuthUsername; cd.pass = cd.req->AuthPassword; AResponseInfo->CloseConnection = ARequestInfo->Connection.LowerCase() != "keep-alive"; switch ( ARequestInfo->CommandType ) { case hcGET: GetCommand( &cd ); break; case hcPOST: PostCommand( &cd ); break; case hcHEAD: HeadCommand( &cd ); break; case hcPUT: break; } #ifdef MY_DEBUG_MODE PushToLogQueue( &cd.log_queue ); #endif #ifdef AUX_MODE int req_time = timer.GetTimeMSec(); if ( stat.dev_req_time < req_time ) Interlocked->Exchange( stat.dev_req_time, req_time ); #endif } //---------------------------------------------------------------------------
  14. заработало 3600 запросов в секунду, пока не падает, в клиенте время запроса 0,7 секунды поднялось с 0,1 и 70% процессорного времени попробую теперь без обращения к пулу, без критических секций, как время ответа измениться и до краша догнать
  15. Пытаюсь изменить код в исходниках System.Classes.pas: constructor TThread.Create(CreateSuspended: Boolean); -//- {$IF Defined(MSWINDOWS)} //#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000 //#define CREATE_SUSPENDED 0x00000004 //FHandle := BeginThread(nil, 0, @ThreadProc, Pointer(Self), CREATE_SUSPENDED, FThreadID); FHandle := BeginThread(nil, 65536, @ThreadProc, Pointer(Self), $00010004, FThreadID); // изменения тут if FHandle = 0 then raise EThread.CreateResFmt(@SThreadCreateError, [SysErrorMessage(GetLastError)]); компилируется, создаю System.Classes.hpp, однако нет эффекта совсем, удалял совсем стоку создания потока BeginThread - никакого эффекта, видимо rtl не так просто изменить. как применить изменения?