optymalizacja kodu

0

Witam...

Mam pewien problem z optymalizacją szybkości mojego kodu...

Mianowicie...

Mam klasę która mniej więcej wygląda tak:

class Spline {
Spline(int step ArrayList<Integer> x , ArrayList<Short> y ){

}

}
z tej klasy pobieram jedną wartość
od razu powwiem że klasa ma za zadanie obliczyć funkcję sklejaną pomiędzy dwomapunktami (x,y) pobranymi z ArrayList (odpowiednio x,y).
Arraylisty to zbiory punktów. Tych punktów jest około 500 i dla każdych sąsiadujących punktów jest wyznaczana nowa funkcja z klasy spline czyli :
dla pkt1(x1,y1) i pkt2(x2,y2) wyznaczamy funkcję (która dla parametru step znajdującego się pomiędzy x1 a x2 wyznaczy odpowiednią wartość y) dla pkt2(x2,y2) i pkt3(x3,y3) nową funkcję itd.
Czyli bardzo dużo razy używam klasy Spline.
Klasy tej używam w metodzie która znajduje się w klasie głównej mojego programu.
Gdy uruchamiam program - wykonuje się on baaardzo wolno...Gdy odpalam profile'a dla CPU to mi wyrzuca że właśnie tam metoda w której użyłem klasy Spline zajmuje najwięcej czasu.

Może wie ktoś jak usprawnić ten kod...

Może wtwalić tą klasę a zrobić z niej normalną metodę...
i jeszcze jedno--- metoda w której użyłem klasy Spline jest używana wielokrotnie

gdyby ktoś miał pomysł...byłbym wdzięczny Razz)
pozdr.

0

Cześć,

za każdym razem, gdy wywołujesz metodę spline, to przekazujesz jej dwie tablice o rozmiarach ok. 500, tylko po to aby wykorzystać z tych tablic 3 wartości. To nie jest wydajna metoda, a jeszcze jak często będziesz ją wywoływał, to aplikacja może Ci przez to zamulić.

Spróbuj tak:
Stwórz klasę Punkt, która przechowuje dwie zmienne x, y.
Następnie w głównej klasie Twojej aplikacji deklarujesz sobie zmienną: List<Punkt> punkty = new ArrayList<Punkt>(500);
Następnie tworzysz metodę(wybór miejsca należy do Ciebie) spline(Punkt p1, Punkt p2, Punkt p3){...}, która z dwóch punktów oblicza wartości dla trzeciego punktu.
Metodzie przekazujesz odpowiednie punkty z listy.

Na przyszłość postaraj się kodować bardziej obiektowo, jeśli architektura MVC jest Ci obca, to poczytaj o niej trochę, ułatwia to programowanie.

mam nadzieję, że pomogłem,
udanych kompilacji,
pozdrawiam serdecznie

0

Wrzuć cały kod bo szklanej kuli nie mamy. Tzn najpierw trochę go poobcinaj, ale tak, żeby dalej się tak samo zachowywał.

0
public class Spline {

    double[] px;
    double[] py;


    public Spline(int step, ArrayList<Integer> X, ArrayList<Short> Y) {

        int x = X.size();
        int y = Y.size();
        px = new double[x];
        py = new double[y];     
        for (int i = 0; i < x; i++) {
            px[i] = (double) parX.get(i);
            py[i] = (double) parY.get(i);
        }
        /* tutaj jakieś obliczenia
         * generalnie tworzę tutaj wszystkie funkcje dla wszystkich splajnów(funkcji sklejanych)
         * Wyniki czyli współczynniki przy iksach zapisuje do tablicy dwuwymiarowej(zapisuje wszystkie współczynniki dla wszystkich przedziałów).
         * Podając wartość step (czyli wartosć iks którą chce znaleźć) konstruktor wyszukuje 
         * odpowiednie do niego współczynniki(uzależnione od tego w jakim przedziale wartości x jesteśmy) i oblicza warość y 
         * 
         */

    }
} 

a w takiej metodzie umieściłem użycie tej klasy :

 void makeCubic(ArrayList<Integer> x, ArrayList<Short> y, ArrayList<Short> val) {
        int si = x.size();
        int begin = x.get(0);
        int end = x.get(si - 1);
        val.clear();

        for (int i = begin; i < end; i++) {
            Spline spl = new Spline(i, x, y);
            val.add((short) spl.polygon);
        }
    }

ArrayLista val to miejsce gdzie wrzucam wszystkie obliczone wartości y
polygon - to po prostu zmienna typu y = a + bx + cxx + dxxx

Może coś wam się uda z tego zrozumieć...Ja tymczasem zajmę się tymco powiedział dRum. Może mi coś wyjdzie..

Kodu z konstruktora spline nie wrzucałem bo dalej tam idzie rozkład LU (dużo matematyki - nic poza tym) ale ogólnie

wynikiem działań jest stworzona tablica współczynników przy iksie a za pomocą tego obliczenie polygon czyli równania kwadratowego ()
gdzie : i - to dana wartość x

0

Niewiele widać w tym kodzie, ale czy przypadkiem nie robisz dużo powtarzających się obliczeń na tych samych danych? Albo czy nie liczysz czegoś, czego później nie używasz?

0

Mieliście racje....

niepotrzebnie w makeCubic tworzyłem obiekt Spline w pętli...
Po drobnej modyfikacji przesunąłem tworzenie obiektu poza iterację dzięki czemu tablicę z współczynnikami tworzę tylko raz.

Tym samym z 73tys ms czas trwania obliczeń dla tej metody spadły do 530 ms.

Teraz chodzi jak przecinak....

Dzięki wielkie sam bym na to nie wpadł :)

tak to teraz wygląda:

 
 void makeCubic(ArrayList<Integer> x, ArrayList<Short> y, ArrayList<Short> val) {
        int si = x.size();
        int begin = x.get(0);
        int end = x.get(si - 1);
        val.clear();
        Spline spl = new Spline( x, y);
        for (int i = begin; i < end; i++) {            
            val.add((short) spl.getYvalue(i));
        }
    }

Mam jeszcze takie pytanko...może się zdażyć że to będzie głupie pytanie :/

lepiej wykonywać działania w konstruktorze klasy czy stworzyć metodę ? co będzie szybciej działać?

0

Możesz stworzyć obiekt Spline, który w konstruktorze tylko przepisuje parametry do pól oraz np implementuje interfejs Iterable i np w metodzie interator() sprawdzałby czy wyniki są już policzone (np if (wyniki != null) chociaż sam if nie jest thread-safe, pasuje dorzucić synchronizację, jeśli będziesz rozrzucał obiekt po kilku wątkach), w razie potrzeby je liczył, a potem konstruował i zwracał iterator. Obiekty, które implementują interfejs Iterable<T> mogą być użyte w pętli for-each: for(T obiekt : implementacjaIterableDlaTypuT).

A co będzie szybsze? Chyba nie ma różnicy skoro wykorzystywane obiekty są takie same i ilość pracy jest też ta sama.

0

Dorzuciłbym tylko, że konstruktor służy do konstruowania obiektu. Jeżeli przeprowadzenie jakichś obliczeń jest warunkiem istnienia lub poprawności obiektu i nie ma możliwości aby pojawiła się wśród nich jakaś sytuacja wyjątkowa, to wtedy należy je wpakować do konstruktora. Jeżeli obliczenia te można podzielić na te, które są warunkiem istnienia obiektu i pozostałe, to należy to zrobić. W każdym innym przypadku do metody lub wielu metod. Czas wykonania konstruktora powinien być jak najmniejszy ponieważ wywołanie utworzenia obiektu jest nierzadko obciążone wywołaniem systemowym, czyli przydziałem pamięci z puli systemu.

0

Czas wykonania konstruktora powinien być jak najmniejszy ponieważ wywołanie utworzenia obiektu jest nierzadko obciążone wywołaniem systemowym, czyli przydziałem pamięci z puli systemu.

Tzn co ma jedno do drugiego? Konstruktor jest zawsze wywoływany po przydzieleniu pamięci na obiekt przecież, a dokładniej tuż po tym.

0

W metodzie.

0

potrenuję :)

dzięki wam za pomoc: )

Pozdro 600

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