Jakie są wymagania sprzętowe do aplikacji?

0

Witam wszystkich!
Pisze program w Dlephi 5.0, i jego kod źródłowy aktualnie ma ponad 6 tys. linijek. Znajduje się w nim kilka tablic, zmiennych (globalnych, globalnych), rekordów itp. Programik na moim kompie (procek to 1,6 GHz; 768 MBDDR RAM) uruchamia się bez problemu, natomiast w pracy przy procku 1,0GHz i chyba 64RAM, czasem się zawiesza. Czy w związku z tym jest może jakiś sposób na sprawdzenie jakie wymagania sprzętowe powinien mieć komp, aby wszystko działało poprawnie? Exe'k zajmuje ok. 600KB
Tylko nie piszcie, że pozostało mi tylko zoptymalizować kod :/

0

W API jest funkcja GlobalMemoryStatus, która zwraca strukturę MemoryStatus.

typedef struct _MEMORYSTATUS { // mst  
    DWORD dwLength;        // sizeof(MEMORYSTATUS) 
    DWORD dwMemoryLoad;    // percent of memory in use 
    DWORD dwTotalPhys;     // bytes of physical memory 
    DWORD dwAvailPhys;     // free physical memory bytes 
    DWORD dwTotalPageFile; // bytes of paging file 
    DWORD dwAvailPageFile; // free bytes of paging file 
    DWORD dwTotalVirtual;  // user bytes of address space 
    DWORD dwAvailVirtual;  // free user bytes 

} MEMORYSTATUS, *LPMEMORYSTATUS; 

Members

dwLength

Indicates the size of the structure. The calling process should set this member prior to calling GlobalMemoryStatus.

dwMemoryLoad

Specifies a number between 0 and 100 that gives a general idea of current memory utilization, in which 0 indicates no memory use and 100 indicates full memory use.

dwTotalPhys

Indicates the total number of bytes of physical memory.

dwAvailPhys

Indicates the number of bytes of physical memory available.

dwTotalPageFile

Indicates the total number of bytes that can be stored in the paging file. Note that this number does not represent the actual physical size of the paging file on disk.

dwAvailPageFile

Indicates the number of bytes available in the paging file.

dwTotalVirtual

Indicates the total number of bytes that can be described in the user mode portion of the virtual address space of the calling process.

dwAvailVirtual

Indicates the number of bytes of unreserved and uncommitted memory in the user mode portion of the virtual address space of the calling process.

W OnCreate pobierz pamięć, dzięki temu wiesz ile masz na starcie. Zapisz do pliku.
Dodaj jakiś przycisk na formę, pootwieraj wszystko co masz w programie i znowu pobierz pamięć. Zapisz do pliku. Nas interesuje pole dwAvailPhys czyli dostępna pamięć. Oblicz różnicę i wiesz ile bierze program. Podczas startu systemu wystarczy dodać warunek:

 if MemoryStatus.dwAvailPhys < To_Co_Obliczyłeś then
  begin
   ShowMessage('Za mało pamięci');
   Application.Terminate;
  end;

Dziwi mnie trochę, że program się wiesza. Ja pisałem 10-tysięcznika, który wczytwuje około 70MB tablic. Wszystko realizuję na wskaźnikach. Tzn. jeżeli czegoś nie potrzebuję to zwalniam pamięć. Pomyśl nad dynamiczną deklaracją niektórych tablic. Powinno pomóc, a przeróbka programu będzie niewielka.
Później wystarczy dać New I Dispose i masz gotową optymalizację.

0

Gdy zabraknie pamięci to program się nie zawiesza - w delphi wygląda to tak:
alokujesz i brak ramu to jest generowany wyjątek, dalej będzie komunikat i ostatecznie -> terminate.

Pewnie masz za dużo zmiennych globalnych - grube MB.

Niektórzy szczególnie uzdolnieni deklarują bezpośrednio takie malutkie globalne tablice:

var tabliczka : array[1..10000, 1..10000] of integer;

pewnie też masz z 5 sztuk takich i 8 trochę mniejszych. :-D

Obiekty powyżej kilkuset bytesów trzeba zawsze tworzyć dynamicznie.
...tak, tak, wiem, wiem - komputery mają teraz setki i tysiące MB, więc można szaleć...

0

Jeżeli chodzi o tablice to byłeś blisko :-), może nie mam tylu co podałeś, ale mam za to pięć takich tablic

var tabliczka : array[1..4, 1.. 5000] of integer;

</b>.

Dodam jeszcze fakt, że program zawiesza się w tym samym miejscu, co jakiś czas, i jak dobrze pamiętam (gdyż jesem w pracy, a programik w domu), to tam właśnie jest operacja na dwóch albo trzech tablicach. Jeżeli chodzi o kompa w pracy to jest to Win'2000 z prockiem 1GHz i 128MB RAMu.

Czyli najlepszym rozwiązaniem byłyby tablice dynamiczne?

0

Tak. Tylko pamiętaj o zwalnianiu!

0

Czy ktoś mógłby mi powiedzieć jak zwolnić tą pamięć?
Szukałem w necie i doczytałem się o tych stosach, stertach, lifo, fifo i już mi się wszystko wymieszało. Ale nie wiem jak to zrobić :-(. Ktoś pomoże?

0

Jakbys czytał uważnie mojego posta to byś wiedział

type
 PTablica = ^TTablica;
 TTablica = array [1..50000] of Integer;

var
 Tablica :PTablica;

begin
 New(Tablica); // tworzenie
 x := Tablica^[indeks]; // odczyt
 Tablica^[indeks] := x;  // zapis
 Dispose(Tablica); // zwalnianie pamięci
end;

Można też odwoływać się przez wskaźnikii, ale nie chcę mieszać.

PS. Masz tablicę integer. Przemyśl dobrze czy nie wystarczy np. Byte. Zaoszczędzisz 50% pamięci.

0

Czyli mam rozumieć że to by wyglądało w następujący sposób (zakładając żę po wciśnieciu buttona) :

procedure TForm1.pokaz_bazeClick(Sender: TObject);
begin
 New(Tablica); // tworzenie
 x := Tablica^[indeks]; // odczyt
// i w tym miejscu mają być instrukcje które zmieniają np. elementy tej tablicy??
 Tablica^[indeks] := x;  // zapis
 Dispose(Tablica); // zwalnianie pamięci
end;
0
Cawon napisał(a)
var tabliczka : array[1..4, 1.. 5000] of integer;

</b>.

Dodam jeszcze fakt, że program zawiesza się w tym samym miejscu, co jakiś czas, i jak dobrze pamiętam (gdyż jesem w pracy, a programik w domu), to tam właśnie jest operacja na dwóch albo trzech tablicach. Jeżeli chodzi o kompa w pracy to jest to Win'2000 z prockiem 1GHz i 128MB RAMu.

Czyli najlepszym rozwiązaniem byłyby tablice dynamiczne?

Jedna taka tablica zajmuje: 450004 = 80000 B
5 sztuk to poniżej 500KB = 0.5MB
Nie jest to wielkość, która pożre 30MB - a tyle powinno być dostępne, gdy jest 128MB w systemie.

Ile program zajmuje pamięci możesz sprawdzić w Menedżerze programów.

Masz inny błąd -> sprawdź algorytm - warunki w pętlach...

0
grizelda napisał(a)

Jedna taka tablica zajmuje: 450004 = 80000 B
5 sztuk to poniżej 500KB = 0.5MB
Nie jest to wielkość, która pożre 30MB - a tyle powinno być dostępne, gdy jest 128MB w systemie.

Ile program zajmuje pamięci możesz sprawdzić w Menedżerze programów.

Masz inny błąd -> sprawdź algorytm - warunki w pętlach...

Jeżeli masz na myśli Menedzer zadań pod windowsem i tam sprawdzenie użycia pamięci do mojego programu, to ta wartość przy samym starcie wynosi 3500K, natomist w miejscu (w programie, gdzie się zawiesza komp w mojej pracyy) wynosi 3700K-3800K.

Inny błąd, algorytm, warunki, pętle? Hm... jeżeli byłyby one żle napisane, wówczas na moim domowym kompie też byłby taki problem (z wieszaniem się). A nie jest tak. Jednym słowem jest to dla mnie dziwne.
Spróbuje jeszcze z tym zwalnianiem pamięci, ale czekam na odpowiedz, podpowiedz mojego ostatniego postu :-)

Z góry dzięki

0

Zapodaj program w downloadzie, wtedy ściągniemy, potestujemi i podpowiemy. Dodaj źródła.

0
Oleksy_Adam napisał(a)

PS. Masz tablicę integer. Przemyśl dobrze czy nie wystarczy np. Byte. Zaoszczędzisz 50% pamięci.
chyba 75% :>

a co do pytania głównego to na 90% masz błąd w algorytmie i zapewne zapętla się gdzies przy sprawdzaniu tych tablic.
Po pierwsze zmienne globalne to ostateczność i nie należy do nich ładować dużych danych.
Po drugie być może tablice dynamiczne będą dla Ciebie rozwiązaniem - zawsze potrzebujesz tak dużych tablic :>
Po trzecie może przydadzą Ci się MemoryTable (np. KBMemTable) - działa jak zwykła TTable ale trzyma dane w pamięci - można dodawać, usuwać, szukać itp.

0

Jeszcze będę próbował, sprawdze algorytmy, pętle, zmienie tablice itp. Jakby co to sie jeszcze odezwę :-)

0
Oleksy_Adam napisał(a)

Później wystarczy dać New I Dispose i masz gotową optymalizację.

W Delphi New i Dispose nie jest potrzebne do tablic dynamicznych.

Tablica dynamiczna zadeklarowana (np. X: array of array of integer - dwuwymiarowa) ma znikomy rozmiar, bo jest wskaźnikiem.

Pamięć przydziela się SetLength. W przypadku dwuwymiarowej najpierw SetLength(X, 500) - 500 wierszy, potem for i:=0 to High(X) do SetLength(x[i],1000) - każdy wiersz będzie miał długość 1000. Analogicznie przy większej liczbie wymiarów. Jeśli wiersze mają być różnej długości (moga być) to wtedy oczywiście nie przez pętlę.

Pamięć zwalnia się przez przypisanie X:=nil lub przez SetLength(X,0). Oczywiście w przypadku tablicy wielowymiarowej najpierw zwalnia się tablice składow ("wiersze") najniższego rzędu, potem wyższego, a tablice główną (w przykładzie X) na końcu.

0

Nie znikomy tylko 4 bajty ;)

I oprócz SetLength i for można po prostu wykonać SetLength(X, 500, 1000).

0
Ktos napisał(a)

Nie znikomy tylko 4 bajty ;)

No 4 bajty były znikomym rozmiarem nawet wtedy, gdy Bill miał rację mówiąc o 640 kB. A nawet, zaryzykuję twierdzenie, za ZX Spectrum.

Ktos napisał(a)

I oprócz SetLength i for można po prostu wykonać SetLength(X, 500, 1000).

O proszę, taki niby stary jestem, a ciągle się uczę... Ciekawe czy jest znaczący zysk przy wywołaniu z dwoma rozmiarami, czy też "pod spodem" jest taka sama pętla.

0

Miałem dłuższa przerwe.... ale wróciłem

Ten komp miał 128MB, dołozyłem drugą kość 128MB i dalej jest ten sam problem.
Jeżeli jest teraz 256MB RAMu, i pozostając przy tablicach statycznych, dalej się zawiesza (cały czas w tym samym momencie), czy to juz mozna stwierdzić w 100%, że jest to winna kodu, algorytmu, a nie RAMu (256MB) i prcka (1,0GHz)???

0

Prawdę powiedziawszy można się było spodziewać tego od samego początku. To, że program zużywa te 3-4 MB pamięci na kompie trochę słabszym od przeciętnej (1GHz proca i 256 MB ramu IMHO całkowicie wystarcza do większości zastosowań użytkowych) to jeszcze nic wielkiego. Są takie programy, które pożerają 30 razy więcej pamięci (np. podczas ładowania do pamięci całych pliciorów po kilka MB) i jakoś dają radę. Szybszy procesor albo większa pamięć przydaje się do gier albo jakichś specjalistycznych, naukowych zastosowań, przy których komp męczy się z obliczeniami przez kilka dni, operując ogromnymi zbiorami danych (chyba, że napisałeś właśnie taki program ). Nie napisałeś co znaczy, że program "czasem się zawiesza". Tzn. wiesz dokładnie w jakim momencie? W jakich okolicznościach (czy jest jakaś pętla, albo przycina się tylko przy jakichś konkretnych danych)? Czy wyskakuje jakiś komunikat, program się wyłącza, czy po prostu przestaje reagować? Proponowałbym krok po kroku prześledzić kod, czy nie ma tam jakiegoś robactwa. Jeśli już musisz używać dużych tablic i rekordów polecam stosowanie wskaźników. Dla pamięci nie jest istotne jak duża jest struktura danej, byleby się w niej zmieściła (w tym znaczeniu nie ma różnicy między tablicami statycznymi i dynamicznymi). Jeśli jednak taką tablicę przekazujesz gdzieś jako argument, zamordujesz w ten sposób procesor, który te kilkadziesiąt kb będzie musiał skopiować (zamiast 4-bajtowego wskaźnika), a tablice zaczną się mnożyć w pamięci. Nie trzeba deklarować oddzielnego wskaźnika, ani nawet tablic dynamicznych - wystarczy przed argumentem użyć var.
Rozmiar pamięci raczej nie jest przyczyną problemu. Procek? Możliwe, że nie lubi tego programu (zwłaszcza jeśli każe mu się przerzucać tony danych). Czy oba procki różnią się tylko ilością GHz, czy raczej dzieli je kilka klas? Jakie jest użycie procesora w krytycznym momencie? Próbowałeś program na innych maszynach/OS-ach?

0

Witam.

Komputer się zawiesza (tzn. wisi tak długo dopóki nie wyłączysz kompa ;-) ) przy tej samej czynności tj. przy automatycznym wyszukiwaniu nazw.
Prześledziłem kod (kilka razy), i podejrzewam jedną rzecz, a raczej funkcje.

Mniejwięcej wygląda to tak (coś na rodzaj wyszukiwarki):
na formie są komponenty edit i stringgrid (lista np. marki samochodów). Z automatu lista marek samochodów wczytytana jest z pliku 'marki.txt' do listboxa (gdzie jest automatycznie segergowana według nazw), a zaraz potem wynik pokazywany jest w stringgridzie.

Jeżeli nazwa nie zostanie odnaleziona, wówczas program informuje nas o tym, odpowiednim komunikatem.

Bład ukazuje się w momencie:
1- wpisuje nazwe marki, której nie ma --> jest komunikat.
2- pkt.1 powtarzam kilka razy, tyle razy ile mi na to pozwoli progam, ba za n-tym razem się wiesza.
ale... kiedy się zawieszi to w polu edit widzę że ciąg liter nie wskazuje na marke samochodu, która jest w stringu - nie ma w bazie. I w tym momencie powinien ukazać się stosowny komunikat, którego już nie zobaczayłem, gdyż komp zawisł :-)

poniżej kod. A może ktoś zaproponuje inna funkcję, która by dawała taki rezultat? :>

function tform2.automatyczneFind(txtSzukaj:string):shortint;
var
nl,A,TT, ileWierszy,k,h,zz:integer;
txtFind: string;
begin
ilewierszy:=0;


form1.ListBox1.Items.Clear;
form1.ListBox1.Items.LoadFromFile('lista.txt');

        for TT:=0 to form1.ListBox1.Items.Count-1 do

        txtFind:='';
        txtFind:=AnsiUpperCase(trim(txtSzukaj));
        nl:=length(txtFind);

        if (txtFind<>'') then
                begin
                     for tt:=0 to form1.ListBox1.Items.Count-1 do
                       begin
                         if (txtFind=Copy(AnsiUpperCase(trim(form1.ListBox1.Items[tt])),1,nl)) then
                                begin
                                ileWierszy:=ileWierszy+1;
                                form1.ListBox2.Items.add(form1.ListBox1.Items[tt]);
                                form2.StringGrid2.RowCount:=form1.ListBox2.Items.Count+1;

                                 for h:=0 to form1.ListBox2.Items.Count-1 do
                                  form2.StringGrid2.cells[1,h+1]:=form1.listBox2.items[h];

                                end
                          else
                                begin
                                end;  //IF
                      end;  //FOR
                end //IF
                else
                        begin   //ss
                        for k:=1 to form2.StringGrid2.RowCount-1 do form2.StringGrid2.Rows[k].Clear;
                        form2.StringGrid2.RowCount:=2;


                        for tt:=0 to form1.ListBox1.Items.Count-1 do
        BEGIN
        form2.StringGrid2.RowCount:=form2.StringGrid2.RowCount+1;    
        form2.StringGrid2.cells[1,tt+1]:=form1.ListBox1.Items[tt];
        END;
 form2.StringGrid2.RowCount:=form2.StringGrid2.RowCount-1;

                        end;  //pierwsze for


    if (txtFind<>'') and ((form1.ListBox2.Items.Count-1)=-1)and (txtFind<>form2.StringGrid2.Cells[1,1])
    then
    begin
    begin
    if  MessageDlg('Brak takiej pozycji w bazie produktow',mtError,[mbOK],0)=mrOK then begin end else begin end;
    end;

    end;    
     automatyczneFind:=1;
end;
0

Moze i glupio sie wtroce do tematu ale mowimy o tablicy dwu-wymierowej, a piszecie zeby zadeklarowac ja dynamicznie. Da sie to zrobic?

0

Da się:

type
  TTablica = array of array of TSomeType
var
  Tablica: TTablica

a potem:

SetLength(Tablica, I, J)

gdzie I, J to rozmiary tablicy

1 użytkowników online, w tym zalogowanych: 0, gości: 1