Модераторы: Snowy, Poseidon, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> ICS скорость загрузки, Время начала и окончания загрузки равны 
:(
    Опции темы
zedx
Дата 3.10.2010, 17:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Есть некая многопоточная качалка на базе ICS. Особенность в том, что загружаются в большом количестве, до смешного маленькие файлы (от нескольких десятков байт до максимум 50-100 кБ). Пробую организовать мониторинг скорости загрузки/отдачи данных.
Завёл структуру, для хранения статистики загрузки:
Код
TThreadStat = record
    SentCount : int64;     // отправлено, байт
    SentBegin : Cardinal;  // время начала отправления, мс
    SentEnd   : Cardinal;  // время окончания отправления, мс
    RcvdCount : int64;     // загружено, байт
    RcvdBegin : Cardinal;  // время начала загрузки, мс
    RcvdEnd   : Cardinal;  // время окончания загрузки, мс
  end;
 
Определил в ICS события для старта таймеров:
Код
 OnBeforeHeaderSend := FOnBeforeHeaderSend; // перед отправкой хидеров серверу 
 OnRequestHeaderEnd := FOnRequestHeaderEnd; // после отправки хидеров серверу
 OnDocBegin         := FOnDownloadBegin;    // перед началом загрузки данных с сервера
 OnDocData          := FOnDownloadProcess;  // периодически, во время загрузки (буфер 8k)
 OnDocEnd           := FOnDownloadEnd;      // после окончания загрузки


Код

procedure THttpICS.FOnBeforeHeaderSend(Sender: TObject;  const Method: String; Headers: TStrings);
begin
  // ... тут идёт доп. обработка заголовков до передачи их серверу
  HttpStat.SentBegin := FGetTickCount; // upload is starting
end;

procedure THttpICS.FOnRequestHeaderEnd(Sender : TObject);
begin
  HttpStat.SentEnd   := FGetTickCount;  // upload is done
  HttpStat.SentCount := Length(RequestHead)+4; // bytes uploaded (we ignore POST data upload!)
end;

procedure THttpICS.FOnDownloadBegin(Sender: TObject);
begin
  HttpStat.RcvdBegin := FGetTickCount; // download is starting
end;

procedure THttpICS.FOnDownloadProcess(Sender: TObject; Buffer: Pointer; Len: Integer);
begin
  //
end;

procedure THttpICS.FOnDownloadEnd(Sender: TObject);
begin
  HttpStat.RcvdEnd   := FGetTickCount; // download is done
  HttpStat.RcvdCount := RcvdCount+Length(RcvdHeader.Text)+2; // bytes downloaded
end;

{
function THttpICS.FGetTickCount: int64;
var T, F : LARGE_INTEGER;
begin
 QueryPerformanceFrequency(int64(F));
 QueryPerformanceCounter(int64(T));
 Result := trunc(1000 * T.QuadPart/F.QuadPart);
end;
}
function THttpICS.FGetTickCount: Cardinal;
begin
 Result := GetTickCount;
end;


Вот, и в итоге получаю одинаковое время начала и окончания загрузки/отдачи, что сводит на нет, все мои попытки считать скорость...

user posted image

Это что, ограничения точности  GetTickCount (и QueryPerformance)? И как, собственно, это можно победить?


PM MAIL   Вверх
RA
Дата 4.10.2010, 00:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Брутальный буратина
****


Профиль
Группа: Участник Клуба
Сообщений: 3497
Регистрация: 31.3.2002
Где: Лес

Репутация: 10
Всего: 115



В составе последнего пакетика ICS есть компонент TMultipartHttpDownloader специально для многопоточной скачки, так вот у него есть хорошие свойсва на борту:    
Код

            'Bytes: ' + IntToStr(MPHttp.TotalCount) +
             '   %: ' + Format('%3.0f', [MPHttp.PercentDone]) +
          '   Kbps: ' + Format('%6.2f', [MPHttp.CurSpeed]) +
        '  Elapsed: ' + FormatDateTime('hh:nn:ss', MPHttp.ElapsedTime);



Так что советую использовать его, ну или посмотреть как в нём это реализованно, всё-таки он наследник от HttpCli
PM   Вверх
zedx
Дата 4.10.2010, 08:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Цитата
TMultipartHttpDownloader специально для многопоточной скачки

Я так понял, это для многопоточной скачки одного большого файла (чанками)? 
Подсчёт статистики реализован через таймер, который срабатывает раз в секунду (предполагается что мы всю эту секунду качали?) - очень грубо и мне такое совсем не поможет.
Код
FCurSpeed    := 8 * (FTotalCount - FPrevCount) / (Tick - FPrevTick);

И идёт подсчёт только скорости загрузки. Исходящая скорость не учитывается...
PM MAIL   Вверх
RA
Дата 4.10.2010, 12:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Брутальный буратина
****


Профиль
Группа: Участник Клуба
Сообщений: 3497
Регистрация: 31.3.2002
Где: Лес

Репутация: 10
Всего: 115



Странно что у тебя GetTickCount возвращает одно и тоже время, может ошибка именно в его получении ? Или в отображении ?
PM   Вверх
zedx
Дата 4.10.2010, 14:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Кхм, какая тут может быть ошибка:
Код
function THttpICS.FGetTickCount: Cardinal;
begin
 Result := GetTickCount;
end;

Где-то краем уха слышал, что точность GetTickCount равна 10-20 милисекунд (так же, как и команды sleep)...
PM MAIL   Вверх
RA
Дата 4.10.2010, 16:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Брутальный буратина
****


Профиль
Группа: Участник Клуба
Сообщений: 3497
Регистрация: 31.3.2002
Где: Лес

Репутация: 10
Всего: 115



Кажется я разобрался в чём дело,
 OnRequestHeaderEnd - Вызывается перед началом форматирования отправляемого заголовка а не // после отправки хидеров серверу так что фактически равен OnBeforeHeaderSend, а OnDocBegin - Вызывается после того как часть данных уже получена.


Для засекания времени исходящего трафика нужно юзать события
 OnSendBegin - время начала отправки
 OnSendEnd - время конца отправки
 OnSendData - изменения в Буфере отправки



Для входящего
 в событии OnStateChange ловим
  httpWaitingHeader или httpWaitingBody
 (в зависимости от наличия шапки)  - И это будет время начала принятия данных.


 OnDocEnd - Время окончания получения данных, хотя может и не самый лучший момент ...

Это сообщение отредактировал(а) RA - 4.10.2010, 16:40
PM   Вверх
zedx
Дата 4.10.2010, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 63
Регистрация: 29.11.2007

Репутация: нет
Всего: нет



Полный мрак :(
- OnRequestHeaderEnd: возникает не после передачи заголовков, а после засылки их в буфер.
- OnSendBegin, OnSendEnd, OnSendData: события при отправке тела запроса (POST). Заголовок же к этому времени уже отправлен. При GET и HEAD запросах не возникают.
- httpWaitingHeader: срабатывает ещё до начала формирования заголовков запроса (перед OnBeforeHeaderSend и OnRequestHeaderEnd).
- httpWaitingBody: срабатывает, когда часть данных (буфер в 8k?), а в моём случае всё тело уже получено (т.е. аналогично OnDocBegin).

Т.е. имеем, что начало запроса определяем по OnBeforeHeaderSend, окончание ответа - по OnDocEnd. Вопрос: как определить "момент истины" когда начинаем получать от сервера хидеры?

Upd: Событие OnHeaderBegin, которое по описанию  http://www.webdelphi.ru/2010/05/ics-v-delp...onenta-httpcli/ должно бы срабатывать до "момента получения первого зоголовка от сервера" так же срабатывает после получения буфера.

Это сообщение отредактировал(а) zedx - 4.10.2010, 20:10
PM MAIL   Вверх
RA
Дата 5.10.2010, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Брутальный буратина
****


Профиль
Группа: Участник Клуба
Сообщений: 3497
Регистрация: 31.3.2002
Где: Лес

Репутация: 10
Всего: 115



Цитата(zedx @  4.10.2010,  19:11 Найти цитируемый пост)
Т.е. имеем, что начало запроса определяем по OnBeforeHeaderSend, окончание ответа - по OnDocEnd. Вопрос: как определить "момент истины" когда начинаем получать от сервера хидеры?


Тогда никак, тут супер точности не достичь. Нужно править компонент, потом патч прислать автору. Собственно в такой форме ICS и существует кто-то что-то где-то исправил и прислал патч. Но люди всё равно любят ICS видимо каждый за своё...
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Сети"
Snowy
Poseidon
MetalFan

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делится вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи

Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Snowy, Poseidon, MetalFan.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0740 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.