Vraag:
OOP versus inline met Arduino
Andy Braham
2015-11-21 01:32:38 UTC
view on stackexchange narkive permalink

Ik ben al een tijdje aan het programmeren, maar ik ben nieuw bij Arduino en AVR Programming. De belangrijkste vraag die ik heb over het programmeren van deze microcontrollers is: zijn er grote verschillen in het ontwerpen van code in objectgeoriënteerde klassen versus de meer traditionele inline-programmering die ik in veel voorbeelden heb gezien?

Met andere woorden, zijn er in de wereld van Arduino / AVR-controllers besparingen met geheugen en prestaties door klassen te gebruiken of omgekeerd?

Stel dat we bijvoorbeeld een klasse hebben:

  class SomeClass () {private: int x; int y; public: void foo (); void bar ();} SomeClass thisClass; thisClass.foo (); thisClass.bar ();  

Zou er enige prestatie- of geheugenwinst zijn door het programma op een meer inline manier te ontwerpen, zoals:

  int x; int y; void foo () {/ *** Doe iets *** /}; void bar () {/ *** Doe meer *** /} ;  

Ik heb geprobeerd een aantal zoekopdrachten uit te voeren op Stack Exchange en Google, maar ik kon het antwoord niet helemaal vinden. Ik ben op zoek naar het dichtstbijzijnde dat ik kon vinden, was deze Stack Exchange-vraag .

De reden dat ik hiernaar vraag, is dat ik een project heb dat zo licht mogelijk moet zijn en dat ik niet duidelijk ben hoe ik mijn programma in deze omgeving moet ontwerpen.


Bewerken

Bedankt voor de antwoorden, dit heeft licht op zaken geworpen. Er is één ding waar ik niet helemaal duidelijk over ben.

Stel dat u een klasse heeft die u ontwerpt die de u8glib als volgt gebruikt:

  class UserInterface {private: U8GLIB_ST7920_128X64 Display; public: UserInterface ();}  

Hoe zou u "Dynamisch geheugen" gebruiken, zoals:

  UserInterface :: UserInterface () {UserInterface :: Display = U8GLIB_ST7920_128X64 (LCD_E_PIN, LCD_RW_PIN, LCD_RS_PIN , U8G_PIN_NONE);}  
Twee antwoorden:
Majenko
2015-11-21 01:56:23 UTC
view on stackexchange narkive permalink

De reden dat je het antwoord niet kunt vinden, is omdat het antwoord zowel Ja als Nee is.

Voor basisklassen - het definiëren van je klas met methoden enz. en het instantiëren van objecten ervan - is er weinig verschil in het eindresultaat vergeleken met "vanilla" C. De optimalisaties van de compiler zijn nu zo goed dat de prestaties precies hetzelfde zijn. Ja, er kan een lichte toename zijn in het geheugengebruik, aangezien je een extra pointer doorgeeft bij elke methodeaanroep (in plaats van foo (int x) heb je foo (MyClass * this, int x ) ) maar dat is zo klein dat het niet opvalt.

De grote verschillen komen wanneer je begint te spelen met polymorfisme en andere geavanceerde onderwerpen. Bij het starten van deze complexe programma's is de compiler niet altijd in staat om uit te zoeken welke functies nodig zijn en welke niet, en kan de ongebruikte functies niet worden verwijderd ( "garbage collection" ). Het is dus heel goed mogelijk dat u grotere code krijgt.

Dat betekent niet dat de code langzamer is, maar alleen stukjes code die rondhangen die nooit iets doen.

Van groter belang is het beheren uw dynamisch geheugen beter dan u gewend bent. Omdat er zo'n kleine hoeveelheid geheugen is, is de heap erg klein, en als gevolg daarvan raakt deze erg gemakkelijk gefragmenteerd. Dynamische creatie en vernietiging van objecten ( nieuwe myClass , delete myClassObject , enz.) Is erg slecht. Klasseobjecten moeten echt ofwel statisch worden gedefinieerd (in globaal bereik is de meest voorkomende) of tijdelijk worden toegewezen op de stapel (lokale instanties). Anders vraag je om problemen - en de eerste keer dat je weet dat er vreemde dingen gebeuren (geen foutrapporten of uitzonderingen, zie je ...).

Oké, dus als ik dit goed begrijp in deze wereld van programmeren, worden klassen meer gebruikt voor een organisatorische en portabiliteitsrol dan voor echte OOP en moeten dingen statisch en expliciet worden toegewezen in plaats van dynamisch. Geweldig bedankt, dit is heel logisch en verklaart waarom ik voorbeelden heb gezien en wat niet is geschreven zoals ze zijn.
Mikael Patel
2015-12-01 03:37:19 UTC
view on stackexchange narkive permalink

De belangrijkste vraag die ik heb over het programmeren van deze microcontrollers is: zijn er grote verschillen in het ontwerpen van code in Object OrientatedClasses versus de meer traditionele inline-programmering die ik in veel voorbeelden heb gezien?

...

Met andere woorden, in de wereld van Arduino / AVR-controllers zijn er besparingen met geheugen en prestaties door klassen te gebruiken of omgekeerd?

Ja, er is een groot verschil tussen het gebruik van C of C ++ voor kleinschalige embedded systemen zoals Arduino / AVR. Met C ++ kan meer informatie worden verstrekt voor compileroptimalisaties.

Als u een OOP-framework, platform of runtime implementeert, kunnen C ++ en klassen ook helpen met softwarearchitectuur en hergebruik. In Cosa wordt een aantal OOP-ontwerppatronen gebruikt om interfaces te realiseren voor zowel applicatieprogrammeurs als device driver-programmeurs. De meest voorkomende is delegatie.

Het gebruik van abstracte klassen, virtuele lidfuncties, inlining en sjablonen kan helpen om een ​​lagere footprint en betere prestaties te bereiken dan traditionele implementaties. Als voorbeeld zijn de Cosa Pin-klassen X5-X10 sneller dan de Arduino-kern en tegelijkertijd kleiner in footprint. Raadpleeg de benchmarks.

Een ding dat u kunt "afleren" van traditionele C ++ - programmering is het gebruik van nieuw / delete (malloc / gratis). Met een SRAM-grootte van slechts een paar Kbyte is het gebruik van een hoop een groot risico. Het antwoord is statische klassen en op stack gebaseerde gegevens.

Er valt nog veel meer te zeggen over OOP-frameworkarchitectuur, maar ik hoop dat dit helpt bij het beantwoorden van uw eerste vragen.

Proost!

Goed antwoord! Ik heb mijn vraag bijgewerkt met de vraag hoe ik het dynamische geheugen kan omzeilen (nieuw / delete / malloc / gratis). Heeft u input over het niet gebruiken van dynamische geheugentoewijzing? Moet alles wat in de lessen gedeeld moet worden globaal zijn? Dat klinkt niet goed, ik heb altijd geleerd om geen globals te gebruiken als je er iets aan kunt doen.
Een korte opmerking over uw UserInterface-voorbeeld hierboven. Het display is eigenlijk een objectcompositie (geen referentie / aanwijzer), dus je hebt geen nieuwe nodig. U moet de weergave starten. De UserInterface-constructie zou er ongeveer zo uit moeten zien. `UserInterface :: UserInterface (): Display (LCD_E_PIN, LCD_RW_PIN, LCD_RS_PIN, U8G_PIN_NONE) {...}`. De noodzakelijke parameters voor de weergaveconstructor moeten worden doorgegeven aan de constructor UserInterface.
Bij OOP draait alles om inkapseling, het verbergen van gegevens, dus delen zou een minimum moeten zijn (nul). Het doel is om min of meer alleen een aantal globale statische objecten te hebben die op elkaar inwerken. Ze houden de mondiale staat vast en verbergen deze. Voor de objecten zijn de lidgegevens een niet-dynamische lokale toestand. Om het doel te bereiken heb je weer een aantal trucs nodig; programma transformaties.
Een voorbeeld; Overweeg het ontwerp van een BitSet-klasse die een variabel aantal leden kan hebben. De voor de hand liggende oplossing is om het aantal benodigde bytes te berekenen en new / malloc te gebruiken. Een alternatief is om de opslag als parameter door te geven aan de BitSet-constructor. Een derde alternatief is een templateklasse met een aantal elementen als parameter. Dit staat een lidvariabele toe die het benodigde aantal bytes is. Zie [Cosa / BitSet.hh] (https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/BitSet.hh) voor meer details over deze variant van programma-transformatie. Er zijn meer transformaties.
Ik heb mijn UserInterface-voorbeeld bijgewerkt, is dat min of meer de juiste aanpak? Ik denk dat ik nu een heel goed begrip heb van hoe ik moet implementeren wat ik nodig heb.
De Cosa-bibliotheek klinkt alsof deze veel van de functies bevat waar ik naar vraag. Ik ging naar de website en merkte dat het een complete vervanging is van de Arduino Library. Is de overhead en footprint van Cosa vergelijkbaar met de Arduino Library?
Cosa is (volgens benchmarks) heeft hogere prestaties en een lagere geheugenvoetafdruk. De Cosa Pin-klassen zijn bijvoorbeeld X5-X10 sneller dan Arduino / Wiring-functies, Cosa UART (Serial) kan tot 2 Mbps draaien en 100% bandbreedte tot 1 Mbps. Er is ondersteuning voor evenementen, functies met tijd / wachtrij (jobs), fsm, proto-thread, threads, enz. Maar het belangrijkste is dat de klassen zijn ontworpen om samen te werken.
Uw update was niet correct. Het scherm mag niet statisch zijn.
Ik heb mijn vraag opnieuw bijgewerkt, ik dacht dat het display statisch zou moeten zijn, omdat ik maar één exemplaar in het geheugen wilde hebben, omdat er eigenlijk maar één display is.


Deze Q&A is automatisch vertaald vanuit de Engelse taal.De originele inhoud is beschikbaar op stackexchange, waarvoor we bedanken voor de cc by-sa 3.0-licentie waaronder het wordt gedistribueerd.
Loading...