Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 10.09.2015, 11:39   #1
sera.kerch
Пользователь
 
Регистрация: 09.04.2015
Сообщений: 24
По умолчанию Динамические массивы и указатели

Доброе время суток знатоки.
Помогите ускорить немного код , его суть создания дерева из входящих данных ( данные о сетевом пакете: протокол, исх ip, порт, вход ip, порт, размер данных )

переменные и типы
Код:
 Tdp=record
    dp:integer;
    size:integer;
  end;
  Tdip=record
    dip:integer;
    dp:array of Tdp;
  end;
  Tsp=record
    sp:integer;
    dip:array of Tdip;
  end;
  Tsip=record
    sip:integer;
    sp:array of Tsp;
  end;
  Tp=record
    p:integer;
    sip:array of Tsip;
  end;

var

paket:array of Tp;
процедура записи данных
Код:
procedure ip1CapI(proto, sourceIP, destIP,
  SourcePort, DestPort: Integer; data_size: Integer);
var i,k:integer;
  p,sip,sp,dip:integer;
  f:boolean;
begin
// proto
 f:=false;
 k:=high(paket);
 for i:=0 to k do
  if proto=paket[i].p then begin
   p:=i;
   f:=true;
   break;
  end;
 if not f then begin
   k:=k+1;
   SetLength(paket,k+1);
   paket[k].p:=proto;
   p:=k;
 end;
// sourceIP
 f:=false;
 k:=high(paket[p].sip);
 for i:=0 to k do
  if sourceIP=paket[p].sip[i].sip then begin
   sip:=i;
   f:=true;
   break;
  end;
 if not f then begin
   k:=k+1;
   SetLength(paket[p].sip,k+1);
   paket[p].sip[k].sip:=sourceIP;
   sip:=k;
 end;
// SourcePort
 f:=false;
 k:=high(paket[p].sip[sip].sp);
 for i:=0 to k do
  if SourcePort=paket[p].sip[sip].sp[i].sp then begin
   sp:=i;
   f:=true;
   break;
  end;
 if not f then begin
   k:=k+1;
   SetLength(paket[p].sip[sip].sp,k+1);
   paket[p].sip[sip].sp[k].sp:=SourcePort;
   sp:=k;
 end;
// destIP
 f:=false;
 k:=high(paket[p].sip[sip].sp[sp].dip);
 for i:=0 to k do
  if destIP=paket[p].sip[sip].sp[sp].dip[i].dip then begin
   dip:=i;
   f:=true;
   break;
  end;
 if not f then begin
   k:=k+1;
   SetLength(paket[p].sip[sip].sp[sp].dip,k+1);
   paket[p].sip[sip].sp[sp].dip[k].dip:=destIP;
   dip:=k;
 end;
// DestPort
 f:=false;
 k:=high(paket[p].sip[sip].sp[sp].dip[dip].dp);
 for i:=0 to k do
  if DestPort=paket[p].sip[sip].sp[sp].dip[dip].dp[i].dp then begin
   paket[p].sip[sip].sp[sp].dip[dip].dp[i].size:=paket[p].sip[sip].sp[sp].dip[dip].dp[i].size+data_size;
   f:=true;
   break;
  end;
 if not f then begin
   k:=k+1;
   SetLength(paket[p].sip[sip].sp[sp].dip[dip].dp,k+1);
   paket[p].sip[sip].sp[sp].dip[dip].dp[k].dp :=DestPort;
   paket[p].sip[sip].sp[sp].dip[dip].dp[k].size :=data_size;
   inc(savep);
 end;
запись данных в базу

Код:
procedure save2base;
var
 i,p,kp:integer;
 sip,ksip,sp,ksp,dip,kdip,dp,kdp:integer;
 ps,sips,sps,dips,dps,ss,dt:string;
begin

   dt:=IntToStr(DateTimeToUnix(date+time));
   if not sldb.isTransactionOpen then
    sldb.BeginTransaction;
   kp:=high(paket);
   for p:=0 to kp do begin
    ps:=CheckProtocol(paket[p].p);
    ksip:=high(paket[p].sip);
    for sip:=0 to ksip do begin
     sips:=inttostr(paket[p].sip[sip].sip);
     ksp:=high(paket[p].sip[sip].sp);
     for sp:=0 to ksp do begin
      sps:=inttostr(paket[p].sip[sip].sp[sp].sp);
      kdip:=high(paket[p].sip[sip].sp[sp].dip);
      for dip:=0 to kdip do begin
       dips:=inttostr(paket[p].sip[sip].sp[sp].dip[dip].dip);
       kdp:=high(paket[p].sip[sip].sp[sp].dip[dip].dp);
       for dp:=0 to kdp do begin
        dps:=inttostr(paket[p].sip[sip].sp[sp].dip[dip].dp[dp].dp);
        ss:=inttostr(paket[p].sip[sip].sp[sp].dip[dip].dp[dp].size);
        sldb.ExecSQL('insert into net (time,prot,ip1,port1,ip2,port2,size) values("'
            +dt+'","'+ps+'","'+sips+'","'+sps+'","'+dips+'","'+dps+'","'+ss+'")');
       end;
       SetLength(paket[p].sip[sip].sp[sp].dip[dip].dp,0);
      end;
     SetLength(paket[p].sip[sip].sp[sp].dip,0);
     end;
     SetLength(paket[p].sip[sip].sp,0);
    end;
    SetLength(paket[p].sip,0);
   end;
   SetLength(paket,0);
  sldb.Commit;
В общем сама суть в том что "paket[p].sip[sip].sp[sp].dip[dip].dp[dp].size" вот такое обращение долго работает, как его можно сократить?
пробовал :
Код:
tpdp:array of Tdp
pointer(ptdp):=paket[p].sip[sip].sp[sp].dip[dip].dp;
// или
ptdp:=@paket[p].sip[sip].sp[sp].dip[dip].dp;
не работает (((

буду признателен за подсказку, заранее спасибо!
sera.kerch вне форума Ответить с цитированием
Старый 10.09.2015, 11:49   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Как вариант вынос в переменные, если это интерфейсы, то ускорение будет.
Код:
  dt:=IntToStr(DateTimeToUnix(date+time));
   if not sldb.isTransactionOpen then
    sldb.BeginTransaction;
   kp:=high(paket);

   for p:=0 to kp do begin
    ps:=CheckProtocol(paket[p].p);
aSip:=paket[p].sip;
    ksip:=high(aSip);

    for sip:=0 to ksip do begin
aSips:=aSip[sip].sip;
     sips:=inttostr(aSips);
     ksp:=high(aSips[sip].sp);

     for sp:=0 to ksp do begin
aSps:=paket[p].sip[sip].sp[sp];
      sps:=inttostr(aSps.sp);
aDip:=aSps.dip;
      kdip:=high(aDip);

      for dip:=0 to kdip do begin
       dips:=inttostr(aDip[dip].dip);
       kdp:=high(aDip[dip].dp);
aDP:=aDip[dip].dp
       for dp:=0 to kdp do begin
        dps:=inttostr(aDP[dp].dp);
        ss:=inttostr(aDP[dp].size);
        sldb.ExecSQL('insert into net (time,prot,ip1,port1,ip2,port2,size) values("'
            +dt+'","'+ps+'","'+sips+'","'+sps+'","'+dips+'","'+dps+'","'+ss+'")');
       end;
       SetLength(aDP[dip].dp,0);
      end;
     SetLength(aDP,0);
     end;
     SetLength(aSips[sip].sp,0);
    end;
    SetLength(aSips,0);
   end;
   SetLength(paket,0);
  sldb.Commit;
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 10.09.2015, 11:57   #3
sera.kerch
Пользователь
 
Регистрация: 09.04.2015
Сообщений: 24
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Как вариант вынос в переменные, если это интерфейсы, то ускорение будет.
Код:
 
aSip:=paket[p].sip;

aSips:=aSip[sip].sip;

aSps:=paket[p].sip[sip].sp[sp];

aDip:=aSps.dip;

aDP:=aDip[dip].dp
а какого типа переменные нужно указать?
sera.kerch вне форума Ответить с цитированием
Старый 10.09.2015, 12:03   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Не знаю )
Это нужно у тебя спрашивать. Что это за paket такой, какой у него тип.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 10.09.2015, 12:08   #5
sera.kerch
Пользователь
 
Регистрация: 09.04.2015
Сообщений: 24
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Не знаю )
Это нужно у тебя спрашивать. Что это за paket такой, какой у него тип.
в верху написано
Код:
var
paket:array of Tp;
если объявить
Код:
asip:array of Tsip;
то при
Код:
asip:=paket[p].sip;
то выдает ошибку неизвестный тип
sera.kerch вне форума Ответить с цитированием
Старый 10.09.2015, 12:16   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
в верху написано
Не увидел...
Тогда вопрос: Почему ты решил что вешалка именно на paket[p].sip[sip].sp[sp].dip[dip].dp[dp].size
?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 10.09.2015, 12:27   #7
sera.kerch
Пользователь
 
Регистрация: 09.04.2015
Сообщений: 24
По умолчанию

Цитата:
Сообщение от Stilet Посмотреть сообщение
Не увидел...
Тогда вопрос: Почему ты решил что вешалка именно на paket[p].sip[sip].sp[sp].dip[dip].dp[dp].size
?
пробовал другой код
Код:
TPaket=record
   protocol,ip_s,port_s,ip_d,port_d,size:integer;
  end;
var
Pakets:array of TPaket;
// запись в базу
   kp:=high(Pakets);
   for p:=0 to kp do begin
    ps:=CheckProtocol(pakets[p].protocol);
    sips:=inttostr(pakets[p].ip_s);
    sps:=inttostr(pakets[p].port_s);
    dips:=inttostr(pakets[p].ip_d);
    dps:=inttostr(pakets[p].port_d);
    ss:=inttostr(pakets[p].size);
        sldb.ExecSQL('insert into net (time,prot,ip1,port1,ip2,port2,size) values("'
            +dt+'","'+ps+'","'+sips+'","'+sps+'","'+dips+'","'+dps+'","'+ss+'")');
   end;
   SetLength(Pakets,0);
// поиск и добавление
f:=false;
 k:=high(Pakets);
 for i:=0 to k do
  if (Pakets[i].protocol=proto) then
   if(Pakets[i].ip_s=sourceIP) then
    if (Pakets[i].port_s=SourcePort) then
     if (Pakets[i].ip_d=destIP) then
      if (Pakets[i].port_d=DestPort) then begin
       Pakets[i].size:=Pakets[i].size+header_size;
       f:=true;
       break;
      end;

 if not f then begin
  k:=k+1;
  SetLength(Pakets,k+1);
  Pakets[k].protocol:=proto;
  Pakets[k].ip_s:=sourceIP;
  Pakets[k].port_s:=SourcePort;
  Pakets[k].ip_d:=destIP;
  Pakets[k].port_d:=DestPort;
  Pakets[k].size:=header_size;
 end;
в данном случаи поиск в 4 раза медленнее
в моем случаи запись в базу в 3 раза медленнее чем в приведенном выше коде
ну и если разобраться если взять например "paket[p].sip[sip].sp[sp].dip[dip].dp[k].dp :=DestPort;"
выходит что программа несколько раз перемещает указатель на необходимую память, или я ошибаюсь?
sera.kerch вне форума Ответить с цитированием
Старый 10.09.2015, 12:43   #8
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
выходит что программа несколько раз перемещает указатель на необходимую память
Нет. Идет обычная считка из ячеек памяти по номеру ячейки. Указателей тут никаких нет и ничего никуда не перемещается.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 10.09.2015, 13:32   #9
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,542
По умолчанию

1. динамический массив это ВСЕГДА ссылка (также как и TObject) и мы можем передавать и присваивать ее БЕЗ дублирования массивов.
2. выделять память по массив лучше сразу с запасом или по крайней мере порциями.

Как это применить?
пишем 3-5 (столько сколько надо) функций поиска и авто дополнения(при неуспешном поиске) ВСЕХ наших массивов.
c результатом в виде найденной Record нужного типа.

Код:
TP =record p: integer; list: array of ???  end;
Tpaket = array of TP;

function GetProto(paket: Tpaket; proto: integer): TP;
begin
 k:=high(paket);
 result.list:=nil; // ДИНАМИЧЕСКИЙ массив это ссылка и мы ее можеМ присваивать БЕЗ дублирования массивов!!!!
 for i:=0 to k do begin
  if paket[i].list=nil then begin // это пока ПУСТОЙ элемент ??? 
    paket[i].p:=proto;
    SetLength(paket[i].list, 10);
  end;
  if proto=paket[i].p then begin
   result.p:=paket[i].p;
   result.list:=paket[i].list; //мы копируем НЕ массив, а только ссылку НА НЕГО!!!!
   break;
  end;
 end;
 if result.p=nil then begin //мы так и не нашли ???
   k:=length(paket);
   SetLength(paket,k+10);// прибавим сразу МНОГО (аж целых десять!)
   paket[k].p:=proto;
   SetLength(paket[k].list, 10); 
   result.p:=paket[k].p;
   result.list:=paket[k].list;
 end;
end;
Код:
 КОД не менял, хотя его НАДО изменить АНАЛОГИЧНО предыдущей функции
function GetSourceIP(p: ???, sourceIP): TSIP;
begin 
 f:=false;
// k:=high(paket[p].sip); 
  k:=high(p); //работаем с "локальным" массивом (здесь и далее ВЕЗДЕ где встретим paket[p] !!!) 
 for i:=0 to k do
//  if sourceIP=paket[p].sip[i].sip then begin  //ТЕПЕРЬ ЗДЕСЬ должен быть НЕ "длинный" выбор в "глобальном многомерном массиве"
  if sourceIP =p[i].sip then begin // а "короткий" выбор в "заданном ПОД массиве"
   sip:=i;
   f:=true;
   break;
  end;
 if not f then begin
   k:=k+1;
   SetLength(paket[p].sip,k+1);
   paket[p].sip[k].sip:=sourceIP;
   sip:=k;
 end;
end;
и основной КОД
Код:
var
  p: TP;
begin
 P:=GetProto(paket, proto);// proto

 sip:=GetSip(p.list, sourceIP);// sourceIP

 sp:=GetSourcePort(sip.list, sourcePort); // SourcePort

 dip:=GetDestIP(sp.list, DestIP);// destIP

 dp:=GetDestPort(dip.list, DestPort);// DestPort
почему функции?
потому что нам теперь НЕ НУЖНЫ комментарии (оставшиеся в основном коде!)
а еще потому что теперь можно на самом деле обойтись и меньшим числом функций и типов данных, но об этом как нибудь в другой раз (упрощать работающую программу лучше понемногу).
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 10.09.2015 в 13:49.
evg_m вне форума Ответить с цитированием
Старый 10.09.2015, 13:40   #10
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

А кстати Евгений прав, перезапрашивать память это дорого по скорости получается.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Указатели и динамические массивы Placebo228 Общие вопросы C/C++ 4 07.11.2012 16:15
Указатели и динамические массивы С++ Лилия396 Помощь студентам 0 14.05.2012 18:00
Динамические массивы и указатели GrihaI Общие вопросы C/C++ 5 30.05.2010 17:52
Указатели и динамические массивы iiunbreakableii Общие вопросы Delphi 7 04.09.2009 14:43
Указатели и динамические массивы. Airou Общие вопросы C/C++ 5 16.01.2009 19:05