Code Optimierung

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hallo,

    ich beschäftige mich erst seit Kurzem mit Python, habe allerdings einiges an Erfahrung mit anderen Scriptsprachen.

    Zu meinem Projekt:
    Ich habe einen Raspberry (Pi1), auf dem die Haussteuerung (FHEM) läuft, an einem zweiten Raspberry (Pi2) hängt ein RFID Reader, ein Display für Statusausgaben (Wetter aktuell + Forecast, Zeit, Status Alarmanlage), sowie zwei Relais, mit dem die Sirene und die Signalleuchte getriggert werden.

    Auf dem Pi2 habe ich 2 Python Scripte laufen. Das Erste bedient den RFID Reader. Wenn ein gültiger Chip gelesen wird, aktiviert oder deaktiviert es per URL Aufruf die Alarmanlage im Pi1.

    Das zweite Script prüft permanent den Status der Alarmanlage per URL Aufruf, fragt einmal pro Stunde den Wetter Forecast ab und aktualisiert den Display.

    Da beide Scripte permanent laufen ist der Pi2 auch zu 97% ausgelastet, wobei das zweite Script 60% Anteil hat.
    Ich wäre Euch dankbar, wenn Ihr Euch den Code mal anschauen könntet und Ihr Tipps zur Optimierung hättet.
    Vielleicht noch zur Erklärung, von ein paar Besonderheiten. Um sicherzustellen, dass das Script nicht abschmiert, wenn der Pi1 nicht verfügbar ist, fange ich das über ein Timeout ab und blende für diesen Fall einen anderen Screen ein, was super funktioniert. Damit ich den Pi1 nicht mit zu vielen Abfragen bombardiere, habe ich ein paar Counter eingebaut, dass nur bei jedem 10. Durchlauf eine Abfrage losgetreten wird. Das ist nicht wirklich schön gelöst, geht das besser?

    Script für das Display und die GPIO Steuerung:


    Functions für das Display-Script:


    Script für den RFID Reader:


    Functions für den RFID Reader:

    VG F.

  • Hallo Fistandantilus,

    ganz allgemein lässt sich sich CPU-Auslastung durch zwei Techniken verringern:
    - in der Haupt-Ereignisschleife eine Verzögerung von wenigen Millisekunden einbauen
    - statt permanent auf Ereignisse wie den RFID-Reader zu prüfen: Interrupt bzw. bei Python Pseudo-Interrupt nutzen.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Danke, das mit dem Pseudo Interrupt schau ich mir gerade an. Hab nur noch kein passendes Beispiel gefunden.
    Die Verzögerung hab ich auch schon überlegt, sehr viel kann ich da wahrscheinlich aber nicht rausholen, da ich beim Erkennen einens Chips dann auch zeitnah und ohne größere Verzögerung eine Änderung am Display zeigen muss, sonst zieht man schlimmstenfalls den Chip nochmal drüber und sieht dann erst recht keine Reaktion weil der Status Quo wieder erreicht ist.
    Falls das Display Script nach Euren Vorschlägen allerdings um den Faktor X schneller geworden ist, kann ich dann auch wieder delays einbauen :)

  • Hallo Fistandantilus,


    Danke, das mit dem Pseudo Interrupt schau ich mir gerade an. Hab nur noch kein passendes Beispiel gefunden.

    Ach, da gibt's für Python ganz viele Links. Die meisten betrachten irgendwelche Taster. Das ist bei Dir dann ein RFID-Ereignis.


    Die Verzögerung hab ich auch schon überlegt, sehr viel kann ich da wahrscheinlich aber nicht rausholen, da ich beim Erkennen einens Chips dann auch zeitnah und ohne größere Verzögerung eine Änderung am Display zeigen muss, sonst zieht man schlimmstenfalls den Chip nochmal drüber und sieht dann erst recht keine Reaktion weil der Status Quo wieder erreicht ist.

    Und bei den Verzögerungen geht's um 2 bis 5 Millisekunden, oder meinetwegen 10 bis 15 Millisekunden. Das ist zeitnah - und Du wirst überrascht sein, wie sich das auf die CPU-Auslastung auswirkt.

    Und eine Doppelerfassung durch den Bediener kannst Du dadurch vermeiden, indem Du Du z.B. durch eine LED oder über das Display den Status anzeigst. Z.B. RFID-Chip drüber ziehen, Erfasst, Auswertung, Anzeige...

    Solche Programme sollten - wenn keine Ereignisse verarbeitet werden - eine Auslastung von kaum mehr als 2 bis 4% haben. Ansonsten kannst Du nicht davon ausgehen, dass das ganze über längeren Zeitraum stabil läuft, da ja auch einige andere Prozesse immer wieder mal beachtet werden wollen.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • So, dass sleep habe ich jetzt mal eingebaut. Zum Testen auf 200ms. Das Script hat jetzt ca. 40% CPU. Ist zwar immer noch viel, aber schon wesentlich besser. Was merkwürdig ist, dass ich im Prozess Monitor das Script 3x drin stehen habe. Ich nehme aber mal an, dass kommt durch die Fehlerbehandlung bei den URL Abfragen, zur Prüfung, ob der Pi1 da ist ,zustande.
    Das RFID Script steht mit 0% im Monitor drin, selbst wenn die Interrupt Geschichte auch hier noch Optimierung bringen könnte, würde ich den Focus erstmal auf das Script mit der Displayanzeige legen.
    Ist die Displayausgabe per pygame der "Performance" Killer, oder hab ich generell vom Aufbau was suboptimal gestaltet?

  • Vielleicht läuft es noch mehrfach, schonmal daran gedacht? Führe mal so oft

    Code
    sudo pkill skriptname.py

    aus, bis keins mehr da ist, bzw

    Code
    ps -C skriptname.py

    nix mehr anzeigt.

    Ist schwer, zu sagen, was genau soviel Last verursacht, wenn man das Programm so nicht testen kann. Ich würde mal mal alle Funktionsaufrufe auskommentieren und sie nacheinander wieder mit ins Skript nehmen und schauen, wie sich das auf die CPU Last auswirkt. Dann wirst du recht schnell herausfinden, welche Funktion ungünstig gebaut ist. Wenn du das weißt, schreib es mal hier, dann sehe ich mir die genauer an.

    Übrigens:

    Code
    if a == 10:
     a = 0


    kannst du kürzer schreiben als

    Code
    a%=10

    So ne Stelle hab ich grad 2x bei dir gefunden. Macht nur einen sehr kleinen Unterschied für die Performance, sieht aber hübscher aus.

    Ich vermute mal, der Performance-Killer ist das ständige neu anzeigen am Display. Du solltest nur neu zeichnen, wenn sich auch tatsächlich was verändert hat. Also eventuell den vorherigen Status noch speichern und nur dann zeichnen, wenn der neue und der alte Status verschieden sind. Verstehst du, was ich meine?

    Einmal editiert, zuletzt von KrawallKurt (20. Juli 2016 um 21:31)

  • Kleine Anmerkungen:

    - Der Shebang steht eigentlich in der Ersten Zeile, nicht in der zweiten.
    - "alarmcounter" setzt du zZt als string, wieso aber nicht als integer?
    - Das vorherige setzen von 'wetter == ""' obwohl anschließend der Rückgabewert von getweather() für 'wetter' gesetzt wird ist überflüssig.
    - Wofür ist "def handler" ? :s Ich seh zwar das du damit "urlopen" nach 20 Sekunden schließt, aber verstehe nicht wieso ;) Du wiederholst diesbezüglich ziemlich oft den selben Code - wenn das denn wirklich zwingend notwenig ist nutze dafür lieber eine eigene Funktion.
    - "for i in range(1)" ? :-/ Was für ne komische Schleife is das denn? :D
    - Du hast eine functions.py und noch eine functions_rfid Datei in denen aber teilweise die gleichen Funktionen drin stehen, wie zB systemstatus_get() ..Warum? ;)

    Bezüglich pygame wiederholst du auch ständig Code wie zB das initalisieren, den font usw, das bremst enorm aus da du jedes mal den kompletten screen neu zeichnest, nicht nur die Teile die sich verändern... Siehe dazu zB FAQ => Nützliche Links / Linksammlung => python: pygame bewegte Bilder & Optimierungen <- und den darauf nachfolgenden Beitrag. Allerdings weiß ich spontan nicht was deine Konsolenbefehle "tft_bmp" bewirken/machen?


    Du hast mehrere Threads, die Timer, deshalb siehst du vermutlich über "top" auch mehrere Processe laufen, eben Mother und Child.

  • Vielen Dank für Euer Feedback. Ein paar Fragen beantworte ich schonmal auf die Schnelle, den Rest teste ich dann Morgen, wenn ich es schaffe.

    Zitat

    - Der Shebang steht eigentlich in der Ersten Zeile, nicht in der zweiten.


    OK, bau ich um.

    Zitat

    "alarmcounter" setzt du zZt als string, wieso aber nicht als integer?


    passe ich auch an

    Zitat

    Wofür ist "def handler" ?


    Der ist für den Fall, dass sich das read nach dem urlopen totläuft, falls die Verbindung zum Pi1 unterbrochen wurde.

    Zitat

    for i in range(1)


    Hab ich noch gar nicht drüber nachgedacht :D , hast natürlich recht. Den rfid code hab ich irgendwoher kopiert.

    Zitat

    Du hast eine functions.py und noch eine functions_rfid Datei in denen aber teilweise die gleichen Funktionen drin stehen, wie zB systemstatus_get() ..Warum?


    Ich hatte ursprünglich alles in einem File. Meine Überlegung war, da ich die zwei Scripte in 2 parallelen Prozessen laufen lasse, werden auch jedes mal alle Module für jedes Script importiert, obwohl die teilweise dort nicht benötigt werden. Also einfach nur um Ressourcen zu sparen und in jedem Script die nur für sich geltenden Funktionen einzubinden. systemstatus_get() sollte aber die Einzige Dopplung sein.

    Zitat

    Allerdings weiß ich spontan nicht was deine Konsolenbefehle "tft_bmp" bewirken/machen


    Mit pygame wird ein Bild gezeichnet, nach /ram/ als bmp gespeichert und dann mit tft_bmp auf dem Display angezeigt. Ein direktes Zeichnen ist mit dem aktuellen Treiber nicht möglich. Hier die Quellen dazu: C-Berry mit Python ansteuern

    Zitat

    Ich vermute mal, der Performance-Killer ist das ständige neu anzeigen am Display. Du solltest nur neu zeichnen, wenn sich auch tatsächlich was verändert hat. Also eventuell den vorherigen Status noch speichern und nur dann zeichnen, wenn der neue und der alte Status verschieden sind.


    Ist auch meine Vermutung. Da ich aber nicht direkt auf dem Display zeichne, sondern den Umweg über das bmp gehen muss, denke ich fast, das man hier maximal an der Häufigkeit des Zeichnens was tun könnte. Da ich aber die Uhrzeit, sowie die aktuellen Daten meiner Wetterstation anzeige, kann das größte Intervall maximal eine Minute sein. Mit den 200ms sleep hab ich somit die Häufigkeit der Darstellung auf dem Display ebenfalls schon beeinflusst. Wie ich gerade gesehen habe, gibt es einen Framebuffer Treiber, mit dem ich Deinen Vorschlag evtl. umsetzen könnte, da muss ich aber erstmal tief eintauchen, wie das geht. Framebuffer Treiber

    Zitat

    a%=10


    Hast Du einen Link, wo ich sowas nachlesen kann. Google hat mir da grad nicht wirklich geholfen. Zum verkürzen if hab ich was gefunden, aber nirgends was zum %.

    Zitat

    Ist schwer, zu sagen, was genau soviel Last verursacht, wenn man das Programm so nicht testen kann. Ich würde mal mal alle Funktionsaufrufe auskommentieren und sie nacheinander wieder mit ins Skript nehmen...


    Gute Idee, werd ich mal machen.

    Einmal editiert, zuletzt von Fistandantilus (21. Juli 2016 um 00:21)

  • Hallo Fistandantilus,


    Ist schwer, zu sagen, was genau soviel Last verursacht, wenn man das Programm so nicht testen kann. Ich würde mal mal alle Funktionsaufrufe auskommentieren und sie nacheinander wieder mit ins Skript nehmen und schauen, wie sich das auf die CPU Last auswirkt. Dann wirst du recht schnell herausfinden, welche Funktion ungünstig gebaut ist. Wenn du das weißt, schreib es mal hier, dann sehe ich mir die genauer an.


    Schau mal hier nach. Finde ich ganz interessant, da man auf diese Weise feststellen kann, wie oft ein Python-Programm eine Zeile gesehehn hat und wie viel Zeit dort verplempert wurde.

    Wie das für die Programmiersprache Icon funktioniert, hatte ich ja bereits gezeigt.

    Ich nutze das zwar mehr zur Ermittlung der Code-Abdeckung und zur Entdeckung toten Codes bzw. zur Ermittlung, welche Fälle nicht eingetreten sind. Dahinter verbergen sich dann entweder sonst sehr schwer aufdeckbare logische Fehler oder im nicht erreichten Code verbergen sich doch noch potentielle Laufzeitfehler. Aber für Deinen Zweck ist Profiling ein brauchbares Werkzeug.


    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

    2 Mal editiert, zuletzt von Andreas (15. Oktober 2017 um 20:26)

  • Das klingt ja sehr cool. Bei meiner bisherigen Programmiererei spielte Hardware (Display, GIPO, UART usw.) kaum eine Rolle, waren meist nur irgendwelche Frontends, bei denen das mit der Performance meistens keine Probleme gab und falls doch, waren es fast immer komplexe SQL Statements, die optimiert werden mussten. Mit den Tools kann man wirklich nützliche Erkenntnisse erlangen, das schau ich mir definitiv mal an!


  • Mit pygame wird ein Bild gezeichnet, nach /ram/ als bmp gespeichert und dann mit tft_bmp auf dem Display angezeigt. Ein direktes Zeichnen ist mit dem aktuellen Treiber nicht möglich. Hier die Quellen dazu: C-Berry mit Python ansteuern


    Ist auch meine Vermutung. Da ich aber nicht direkt auf dem Display zeichne, sondern den Umweg über das bmp gehen muss, denke ich fast, das man hier maximal an der Häufigkeit des Zeichnens was tun könnte. Da ich aber die Uhrzeit, sowie die aktuellen Daten meiner Wetterstation anzeige, kann das größte Intervall maximal eine Minute sein. Mit den 200ms sleep hab ich somit die Häufigkeit der Darstellung auf dem Display ebenfalls schon beeinflusst. Wie ich gerade gesehen habe, gibt es einen Framebuffer Treiber, mit dem ich Deinen Vorschlag evtl. umsetzen könnte, da muss ich aber erstmal tief eintauchen, wie das geht. Framebuffer Treiber

    Der von Dir verlinkte fb-Treiber ist 2 Jahre alt, würde ich also vermeiden. Nimm lieber den aktuellen Treiber vom Hersteller: http://www.airspayce.com/mikem/bcm2835/index.html

    Den Treiber einrichten sollte relativ schnell gehen:

    Die Tools installieren:

    Code
    cd /usr/src
    wget http://admatec.de/sites/default/files/downloads/C-Berry.tar.gz
    tar xfz C-Berry.tar.gz  && rm C-Berry.tar.gz
    cd C-Berry/SW/tft_test
    make
    ./tft_test

    Mit dem Tool fb2cberry kann man die Ausgabe für /dev/fb0 also dem HDMI Port auch kopieren/clonen:

    Code
    cd /usr/src/C-Berry/SW/fb2cberry
    make
    cp fb2cberry /usr/local/sbin/fb2cberry
    fb2cberry &     #ausfuehren und in den hintergrund schicken, zB in /etc/rc.local eintragen


    Du könntest dann also dein Python Script einfach so schreiben das /dev/fb0 angesprochen wird...

    Code
    os.environ["SDL_FBDEV"] = "/dev/fb0"


    Beachtet das ihr mit einem Pi2 devicetree enabled haben müsst, was aber standardmäßig der Fall sein sollte.

  • OK, wieder eine Aufgabe :D Den aktuellen Treiber habe ich derzeit schon installiert, hatte mich bisher aber noch nicht darum gekümmert, ob damit die Framebuffer Ausgabe funktioniert. Aber egal, das ist erstmal eine andere Baustelle.

    Ich habe mittlerweile mal etwas weiter analysiert. Da all das Aufräumen von doppeltem Code nicht wirklich signifikante Einsparungen gebracht hat, habe ich dann wie von KrawallKurt vorgeschlagen, Teile auskommentiert. So wie es aussieht, ist tatsächlich das Zeichnen der größte Performance Killer.
    pygame.image.save(window, "/ram/temp.bmp") und os.system("tft_bmp /ram/temp.bmp") haben kaum Einfluß. Lasse ich das Zeichnen komplett weg, fällt die Last auf ca. 16% mit den 2 Threads, die durch def handler erzeugt werden.

    Im Umkehrschluss heißt das aber, ich muss doch an den Treiber ran, damit ich dann nur noch selectiv den Screen zeichnen muss. Klingt auf jeden Fall nach sehr viel Arbeit, weil ich mit dem pygame Kram eben auchnoch nicht wirklich was gemach habe, außer dem was jetzt im Code drin steht.

  • Zitat

    Hast Du einen Link, wo ich sowas nachlesen kann. Google hat mir da grad nicht wirklich geholfen. Zum verkürzen if hab ich was gefunden, aber nirgends was zum %.


    % ist der modulo Operator. Da du deine Variable immer nur inkrementierst und bei x wieder auf 0 setzt, kannst du auch gleich variable modulo x machen.


    16% klingt immer noch nach recht viel. Wie oft ändert sich denn bei dir das Wetter? ;) Muss das mehrfach pro Sekunde aktualisiert werden? Nur mal so als Denkanstoß... Allgemein finde ich das mit dem Wetter seltsam. Die Vorhersage wird nur einmal abgerufen, dann nie wieder ^^ Die anderen Werte, die du dir von FHEM holst, kommen die aus dem Netzwerk oder vom Pi selbst? Wenn sie vom Pi selbst kommen, gibt es sicher performantere Möglichkeiten, die auszulesen, als eine URL zu parsen.


    Du musst auch nicht unbedingt selektiv neu zeichnen. Aber wenn sich gar nix ändert, solltest du auch gar nicht zeichnen.

  • Naja mach es erst mal so das du fb2cberry im Hintergrund ausführst.
    Dann erstellst du dir einfach ein neues Script und initialisierst ganz am Anfang das Display und alles was "statisch" immer gleich bleibt, zum Beispiel:

    [code=php]
    os.environ["SDL_FBDEV"] = "/dev/fb0"
    # default screen size
    width = 320
    height = 240

    # colors R G B
    white = (255, 255, 255)
    red = (255, 0, 0)
    green = ( 0, 255, 0)
    blue = ( 0, 0, 255)
    black = ( 0, 0, 0)
    cyan = ( 50, 255, 255)
    magenta = (255, 0, 255)
    yellow = (255, 255, 0)
    orange = (255, 127, 0)

    # --- init screen ---
    size = (width, height)
    pygame.init()
    window = pygame.display.set_mode(size)
    window.fill(black)
    xmax = width - 2
    ymax = height - 1
    # fonts
    font0 = pygame.font.SysFont("droidsans", 21)
    font1 = pygame.font.SysFont("droidsans", 15)
    font2 = pygame.font.SysFont("droidsans", 83)
    font3 = pygame.font.SysFont("droidsans", 33)
    font4 = pygame.font.SysFont("freemono", 26)
    font0.set_bold(1)
    font3.set_bold(1)
    # images
    image = dict()
    image["off48"] = pygame.image.load("/home/webide/repositories/my-pi-projects/Securasp/Icons/status_off48.png").convert_alpha()
    image["on72"] = pygame.image.load("/home/webide/repositories/my-pi-projects/Securasp/Icons/status_on72.png").convert_alpha()
    image["warning72"] = pygame.image.load("/home/webide/repositories/my-pi-projects/Securasp/Icons/status_warning72.png").convert_alpha()
    [/php]
    Die Sachen sind soweit ich das nachvollziehen kann in allen Funktionen identisch.

    Dann scheinst du auch einen Standard "Border" zu haben, wo du dir ebenfalls eine Funktion für anlegen kannst sodass dieser Code nicht ständig wiederholt wird:
    [code=php]
    def screenborder(lines=1, color=white):
    # Draw Screen Border
    pygame.draw.line( window, color, (0,0), (xmax,0), lines )
    pygame.draw.line( window, color, (0,0), (0,ymax), lines )
    pygame.draw.line( window, color, (0,ymax), (xmax,ymax), lines )
    pygame.draw.line( window, color, (xmax,0), (xmax,ymax+2), lines )
    # 2.parallele
    pygame.draw.line( window, color, (0,ymax*0.20), (xmax,ymax*0.20), lines )
    [/php]

    Und dann nimmst du einfach 2 deiner "screen" Funktionen zum testen und schreibst die ein bisschen um:
    [code=php]
    def alertscreen():
    window.fill(red)
    screenborder()
    label0 = font0.render("SECURITY BREACH!!!", 1, black)
    window.blit(label0, (50,10))
    window.blit(image["warning72"], (110,100))

    def offlinescreen():
    window.fill(red)
    screenborder()
    label0 = font0.render("FHEM offline!!!", 1, black)
    window.blit(label0, (50,10))
    window.blit(image["warning72"], (110,100))

    def armedscreen():
    window.fill(green)
    screenborder()
    label0 = font0.render("SYSTEM ARMED!!!", 1, black)
    label1 = font1.render("Please leave house or disarm system", 1, black)
    label2 = font1.render("within 30 seconds before alarm is raised!", 1, black)
    window.blit(label0, (60,10))
    window.blit(label1, (10,180))
    window.blit(label2, (10,200))
    window.blit( image["on72"], (120,100))

    def offscreen(wetter):
    #degree = u"°C"
    degree = u"°C"
    wetter = wetter
    d1 = wetter.get('d1')
    t1 = wetter.get('t1')
    l1 = wetter.get('l1')
    i1 = wetter.get('i1')
    d2 = wetter.get('d2')
    t2 = wetter.get('t2')
    l2 = wetter.get('l2')
    i2 = wetter.get('i2')
    d3 = wetter.get('d3')
    t3 = wetter.get('t3')
    l3 = wetter.get('l3')
    i3 = wetter.get('i3')
    now = datetime.datetime.now()
    vtime = now.strftime("%H:%M")
    vtag = now.strftime("%Y-%m-%d")

    window.fill(black)
    screenborder()
    pygame.draw.line( window, white, (0,ymax*0.5),(xmax,ymax*0.5), 1 )
    pygame.draw.line( window, white, (xmax*0.33,ymax*0.5),(xmax*0.33,ymax), 1 )
    #mittlere senkrechte
    pygame.draw.line( window, white, (xmax*0.5,ymax*0.2),(xmax*0.5,ymax*0.5), 1 )
    pygame.draw.line( window, white, (xmax*0.66,ymax*0.5),(xmax*0.66,ymax), 1 )

    label0 = font0.render("System Status", 1, red)
    labeld1 = font1.render("heute", 1, white)
    labeld2 = font1.render(d2, 1, white)
    labeld3 = font1.render(d3, 1, white)
    window.blit(label0, (10,10))
    window.blit(labeld1, (35,120))
    window.blit(labeld2, (120,120))
    window.blit(labeld3, (225,120))
    icon2 = pygame.image.load("/home/webide/repositories/my-pi-projects/Securasp/Icons/weather/d_"+i1+"_S.png").convert_alpha()
    icon3 = pygame.image.load("/home/webide/repositories/my-pi-projects/Securasp/Icons/weather/d_"+i2+"_S.png").convert_alpha()
    icon4 = pygame.image.load("/home/webide/repositories/my-pi-projects/Securasp/Icons/weather/d_"+i3+"_S.png").convert_alpha()
    window.blit( image["off48"], (240,0))
    window.blit( icon2, (30,140))
    window.blit( icon3, (130,140))
    window.blit( icon4, (235,140))
    labelt1 = font1.render(t1+"/"+l1+degree, 1, white)
    labelt2 = font1.render(t2+"/"+l2+degree, 1, white)
    labelt3 = font1.render(t3+"/"+l3+degree, 1, white)
    window.blit( labelt1, (30,190))
    window.blit( labelt2, (130,190))
    window.blit( labelt3, (235,190))
    labelx1 = font1.render(vtag, 1, white)
    labelx2 = font3.render(vtime, 1, white)
    labelx3 = font1.render("aktuelles Wetter", 1, white)
    window.blit( labelx1, (45,50))
    window.blit( labelx2, (30,80))
    window.blit( labelx3, (185,50))
    (temp, rain, wind) = weather_curr_get()
    labelx4 = font1.render(temp+degree, 1, white)
    labelx5 = font1.render(rain, 1, white)
    labelx6 = font1.render(wind, 1, white)
    window.blit( labelx4, (185,65))
    window.blit( labelx5, (185,80))
    window.blit( labelx6, (185,95))
    [/php]

    Und dann mal probieren entsprechend deines anderen Codes diese neuen Funktionen mal auszuführen ;) Wie gesagt, pygame-Initialisierung noch vor dem Aufruf der Funktionen durchführen, aber auch nur ein mal beim starten des Scripts.

    => http://codepad.org/G2hrVoi6

    Aber auch hier besteht natürlich noch einiges an Optimierungspotenzial :fies:

    Stellst du bereits jetzt weniger CPU Last fest?

  • So, nachdem ich jetzt mal noch einiges umgestellt habe, sieht das Ganze schon ganz gut aus. Den Teil mit dem Treiber habe ich wegen des Aufwands erstmal noch geschoben.
    Da das Script die meiste Zeit den Offscreen anzeigt, habe ich wegen der Uhrzeit alles so gebaut, dass der Screen nur noch 1x pro Minute aktualisiert wird. Die Counter im Hauptprogramm zur Reduzierung der Anfragen auf dem Pi1 habe ich rausgeworfen und dafür den Delay auf 500ms hochgenommen. Das Script für die Anzeige und Relaissteuerung liegt jetzt bei rund 10%, was schon ein enomer Sprung zu vorher ist. Insgesamt liegt der Pi bei etwa 15%, womit ich gut leben kann.

    Vielen Dank für Eure Anregungen und Tipps, die mir sehr weitergeholfen haben!

    Einmal editiert, zuletzt von Fistandantilus (28. Juli 2016 um 09:43)


  • So, nachdem ich jetzt mal noch einiges umgestellt habe, sieht das Ganze schon ganz gut aus. Den Teil mit dem Treiber habe ich wegen des Aufwands erstmal noch geschoben.
    Da das Script die meiste Zeit den Offscreen anzeigt, habe ich wegen der Uhrzeit alles so gebaut, dass der Screen nur noch 1x pro Minute aktualisiert wird. Die Counter im Hauptprogramm zur Reduzierung der Anfragen auf dem Pi1 habe ich rausgeworfen und dafür den Delay auf 500ms hochgenommen. Das Script für die Anzeige und Relaissteuerung liegt jetzt bei rund 10%, was schon ein enomer Sprung zu vorher ist. Insgesamt liegt der Pi bei etwa 15%, womit ich gut leben kann.

    Vielen Dank für Eure Anregungen und Tipps, die mir sehr weitergeholfen haben!

    Magst du uns und anderen die es interessieren könnte dein aktuelles/optimiertes Script zeigen? Ein direkter Vergleich beider Version könnte dann dem ein oder anderen zeigen was die Optimierung beinhaltet hat und was Sie dann für Ihr Projekt ebenfalls beachten könnten.
    :danke_ATDE:

  • Gern, anbei die Scripte.
    Neben den Anpassungen, habe ich auch einiges aufgeräumt, auskommentierte Debug Zeilen rausgeschmissen und den Ablauf im Display Script leicht umstrukturiert. Die Anzeige des normalen Screens, war bisher immer als else Bedingung drin. D.h. das Teil musste immer komplett bis zum Ende abgearbeitet werden, obwohl die Anzeige wahrscheinlich die ist, die am häufigsten zu sehen sein wird. Das wird zwar keine riesigen Laufzeitverbesserungen geben, macht aber denke ich Sinn.

    RFID-Script:

    RFID-Functions:

    Display-Script:

    Display-Functions:


    VG F.

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!