Hallo,
ich habe mal eine allgemeine Frage. Was bevorzugt ihr auf einem µC für
eine Technik bei Benutzung von Strukturen, Arrays usw. ? Erzeugt ihr
statische Arrays (also array[100]) oder arbeitet ihr fleißig mit
malloc/free? Wie gesagt, nicht auf einem PC sondern einem µC.
Funktioniert malloc und free genauso zuverlässig oder ist dies auf dem
µC mit Nachteilen behaftet.
Danke Martin
Ich weiß, dass es viele Gegner von malloc() in einer Controller-
Umgebung gibt. Das Hauptproblem ist: wenn du mit den Ressourcen
am Ende bist, ist es nahezu egal, ob deine statisch vorbelegten
Ressourcen nicht mehr reichen oder der dynamische Speicher alle
ist: sehr oft gibt es dafür einfach keinen vernünftigen Ausweg mehr.
Was dann passieren kann/darf/soll, darüber muss man sich von
vornherein im Klaren sein.
Ich habe gestern eine langjährige Implementierung mit statischen
Tabellen auf malloc() umgestellt, weil mir die Bugs, die beim
notwendigen Umsortieren der statischen Einträge immer wieder
auftraten, nunmehr so sehr auf die Füße gefallen waren, dass ich
einfach keine Lust mehr hatte, dort nochmals Aufwand reinzusetzen.
Was soll ich sagen? Zwei Übersetzungsgänge zum Ausbügeln der
Syntaxfehler, einen Versuchslauf, bei dem sich nach 5 Sekunden ein
Implementierungsfehler gezeigt hat -- und jetzt laufen meine
Stresstests hier durch, an denen ich vorher eine Woche mit dem
Logicanalyzer herum debuggt habe, um dann doch nur festzustellen,
dass das besagte Subsystem offenbar kaputt ist...
p.s.: Mein Lieblingsvergleich von malloc zu statischer Belegung ist der
zwischen Ethernet und Token Ring. Der Token Ring ist die ,,reine
Lehre'': alles ist deterministisch, und bis das Medium wirklich
komplett gesättigt ist, geht alles ganz geregelt seinen Gang. Bei
Ethernet werden Dinge dem Zufall überlassen, und ab 95 % Auslastung
bricht es dann langsam ein. Nur: für die 5 %, die man den Token Ring
dann noch besser benutzen kann, bezahlt man halt einen viel höheren
Preis, da die ganze Verwaltung aufwändig ist. (Und wenn man die 100 %
erreicht hat, muss man sich auch dort dann nach mehr Ressourcen
umsehen.)
Welches der beiden Protokolle überlebt hat, ist mittlerweile ja
ziemlich klar...
Ich: absoluter Gegner von malloc auf nem uC!
Bei statischen Variablen siehst du bei der Entwicklung ob der Speicher
noch reicht, bei Verwendung von malloc weißt du das nie so genau und
fehler zeigen sich unter u. erst im Feld. Außerdem brauchst du mehr Code
weil du immer prüfen musst, ob der Speicher geholt werden konnte.
Außerdem hilft es auch beim debuggen wenn eine Variable immer an der
gleichen Adresse steht.
Hallo,
interessant wie dieses Thema anscheinend polarisiert.
Wenn ich so die Antwort von Hektor lese, tendiere ich zur statischen
Variante, lese ich die von Jörg, dann diese.
Die Wahl des Richtigen ist wohl nicht ganz so einfach.
Gruss
Martin
Auf einem µC ist malloc nun mal sehr schmerzlich
-- es belegt selbst RAM für die Verwaltung
-- es belegt mehr Programmspeicher
-- es braucht mehr Zeit
-- es ist praktisch nicht statisch analysierbar und deshalb in
sicherheitskritischen Anwendungen kaum oder nicht gesehen.
Erste drei Punkte treffen für kleine µC zu, während in
sicherheitskritischen Anwendungen größere µC zum Einsatz kommen. Unter
der Motorhaube Deines PKW gibt es zum Beispiel kein malloc.
In manchen Fällen kann alloca eine Alternative sein, also Code in der
Richtung
1
voidfoo(size_tsize)
2
{
3
type_tvar[size];
4
...
5
}
Vom Overhead ist das günstiger (ebenso von der statischen Analyse her),
aber die so erhaltenen Speicherbereiche sind eben nicht dynamisch
sondern auto (findet sich aber ebensowenig im Auto).
Jörg Wunsch wrote:
> Was soll ich sagen? Zwei Übersetzungsgänge zum Ausbügeln der> Syntaxfehler, einen Versuchslauf, bei dem sich nach 5 Sekunden ein> Implementierungsfehler gezeigt hat -- und jetzt laufen meine> Stresstests hier durch, an denen ich vorher eine Woche mit dem> Logicanalyzer herum debuggt habe, um dann doch nur festzustellen,> dass das besagte Subsystem offenbar kaputt ist...
Soll das jetzt heißen, daß malloc die Fehlersuche vereinfacht?
Ich würde eher sagen, die Beschäftigung mit dem Programm beim Umstellen
hat den Blick geschärft.
Es könnte also auch sein, daß man bei einem anderen Programm beim
Umstellen von malloc auf Tabelllen den Fehler findet.
Das passiert nicht selten, man sitzt tagelang vor einem fremden
Programm, wie das Kaninchen vor der Schlange.
Und erst, wenn man sich richtig tief in die Suppe reinkniet, findet man
den Fehler.
Peter
Johann L. wrote:
> Auf einem µC ist malloc nun mal sehr schmerzlich>> -- es belegt selbst RAM für die Verwaltung
Das ist aber deutlich weniger als das, was du sonst als statische
Vorbelegungen von Ressourcen brauchst, da du ja immer ,,für alle
Fälle'' gewappnet sein musst. In der avr-libc sind es beispielsweise
gerade mal 10 Bytes.
In meinem genannten Falle brauche ich diese 10 Bytes sowie unter
Stressbedingungen ca. 40...50 Bytes an Daten (mit dem Debugger
analysiert). Die frühere statische Lösung besaß zwei Arrays mit
mit insgesamt 224 Bytes.
> -- es belegt mehr Programmspeicher
Ja, auf jeden Fall.
> -- es braucht mehr Zeit
Jein. Kommt drauf an. In meinem oben genannten Fall habe ich es
nicht analysiert, ist aber gut möglich, dass es dort weniger Zeit
braucht als die ständige Umsortiererei der statischen Tabellen
zuvor. Wenn nämlich ein Eintrag abgearbeitet ist, kann ich ihn
einfach ,,wegwerfen'', um die Entsorgung kümmert sich die
Bibliothek.
> -- es ist praktisch nicht statisch analysierbar und deshalb in> sicherheitskritischen Anwendungen kaum oder nicht gesehen.
Ja, klar. Aber wenn's sicherheitskritisch ist, sind die höheren
Kosten für den Ressourcen-Mehrverbrauch einer voll statischen Lösung
normalerweise unproblematisch.
Peter Dannegger wrote:
> Soll das jetzt heißen, daß malloc die Fehlersuche vereinfacht?
Nein, das Problem war schon immer dynamischer Natur und dadurch
mit dynamisch erzeugten Listen viel überschaubarer zu
implementieren.
> Es könnte also auch sein, daß man bei einem anderen Programm beim> Umstellen von malloc auf Tabelllen den Fehler findet.
Die vorige Implementierung hat bereits genügend Entwicklungskosten
hier für ihre Wartung geschluckt, sowohl seitens desjenigen, der
das Original implementiert hat als auch seitens anderer Entwickler.
Sie war (auf Grund der dynamischen Natur des zu Grunde liegenden
Problems) so schwer mit all ihren möglichen Randbedingungen und
möglichen race conditions zu überschauen, dass sie immer wieder
Bugs gezeigt hat.
p.s.: Peter, ich will hier überhaupt nicht in Abrede stellen, dass
man eine Implementierung ohne malloc() hätte finden können, die
bugfrei funktioniert. Die Implementierung mit malloc() war aber nach
all den damit gemachten Erfahrungen der letzten Jahre die in jeder
Hinsicht ökonomischere, und sie hat (für uns) keinerlei Nachteil.
Jörg Wunsch wrote:
> Die Implementierung mit malloc() war aber nach> all den damit gemachten Erfahrungen der letzten Jahre die in jeder> Hinsicht ökonomischere, und sie hat (für uns) keinerlei Nachteil.
Ich kenne jetzt Deine Anwendung nicht.
Es gibt bestimmt für jede Programmierweise auch eine entsprechende
Anwendung, für die diese optimal ist.
Ich hatte ja mal einen Scheduler geschrieben, der auch Einträge
hinzufügen, entfernen und umsortieren muß.
Allerdings sortiert er nicht wirklich um, sondern ändert nur die
Verkettung.
Vielleicht wäre das auch ein Kandidat für malloc.
Peter
Malloc/free wird dann problematisch, wenn es an zwei Stellen eingesetzt
wird, mit jeweils unterschiedlicher Blockgröße. Dann kann es nämlich
passieren, dass der Speicher (durch den Aufruf mit der kleineren
Blockgröße) so fragmentiert ist, dass möglicherweise noch 50% des RAMs
frei sind, aber kein größerer Block mehr alloziert werden kann. (Außer
man betreibt einen Garbage Collector o.ä., aber das wäre dann wirklich
zuviel Overhead)
Peter Dannegger wrote:
> Ich kenne jetzt Deine Anwendung nicht.
Ist eine timer queue.
> Vielleicht wäre das auch ein Kandidat für malloc.
Ja, wenn sich Verkettungen dynamisch ändern können, ist das häufig
damit einfacher abzubilden.
Simon K. wrote:
> Malloc/free wird dann problematisch, wenn es an zwei Stellen eingesetzt> wird, mit jeweils unterschiedlicher Blockgröße. Dann kann es nämlich> passieren, dass der Speicher (durch den Aufruf mit der kleineren> Blockgröße) so fragmentiert ist, dass möglicherweise noch 50% des RAMs> frei sind, aber kein größerer Block mehr alloziert werden kann. (Außer> man betreibt einen Garbage Collector o.ä., aber das wäre dann wirklich> zuviel Overhead)
Klar, Speicherfragmentierung ist immer ein mögliches Problem. Wenn
beide Ereignisse aber einigermaßen zufällig zueinander sind, dann
wird das sich im Betrieb irgendwo einpegeln und danach nicht weiter
fragmentieren.
Wenn man das Ganze während der Probephase mit einem Debugger
beobachten kann, dann kann man anhand der höchsten je durch malloc()
belegten Speicheradresse relativ einfach feststellen, ob sich da
noch was aufschaukelt oder nicht.
Aber zurück zur statischen Variante: in aller Regel werden dieser
in solchen worst-case-Szenarien die Ressourcen bereits viel früher
ausgegangen sein, wo die dynamische Variante durch ihre größere
Flexibilität noch Reserven hat. Sie kann nämlich den Speicher für
Ressource A nie auch alternativ für Ressource B benutzen, während
die dynamische Variante das erst einmal kann.
Ich hoffe, ich klinge jetzt nicht so, als wäre malloc() das
Allheilmittel schlechthin. ;-) Das ist es ganz gewiss auch nicht.
Jedem Problem seine Lösung. malloc() kann es halt durch seine
Flexibilität erlauben, dass eine bestimmte Applikation im normalen
Betrieb die Ressource RAM besser benutzt, wenn die Anforderungen
an diese Ressource nicht vorhersagbar sind und eher zufällig
auftauchen. In derartigen Situationen muss man aber immer (auch
bei statischer Allokierung) den Fall abdecken, dass die Ressourcen
den Anforderungen nicht genügen und einplanen, wie man in diesem
Falle vorgeht.
Wenn alles rein statisch und zur Compilezeit bekannt ist, dann hat
malloc() natürlich absolut keinen Sinn. Wieder andere Probleme
können sich gut mit dem bereits beschriebenen alloca() lösen lassen,
dass die Allokation auf dem Stack erledigt.
Jörg Wunsch wrote:
> Wenn alles rein statisch und zur Compilezeit bekannt ist, dann hat> malloc() natürlich absolut keinen Sinn. Wieder andere Probleme> können sich gut mit dem bereits beschriebenen alloca() lösen lassen,> dass die Allokation auf dem Stack erledigt.
Das sollte man so mal festhalten, da das den meisten Leuten gar nicht so
bewusst ist :-)
Kann man eigentlich irgendwo die malloc-Implementierung von der avrlibc
nachschauen?
PS: Habs schon:
http://cvs.savannah.gnu.org/viewvc/avr-libc/libc/stdlib/malloc.c?revision=1.11&root=avr-libc&view=markup
Ich halte die dynamische Speicherverwaltung mit malloc, wie sie
üblicherweise implementiert ist, auf Systemen, wo mehr als etwa 20%
des RAM-Speichers genutzt werden, für ziemlich gefährlich. Ich hatt
aledings bisher keine µC-Anwendung, bei der ich einen dringenden
Bedarf nach malloc und free sah. Meist konnte man das Problem mit ein
paar zusätzlichen Code-Zeilen anders lösen.
Bei der üblichen Heap-Verwaltung ist auf Grund der Speicherfragmentie-
rung der theoretisch (über beliebig verteilte Datenblöcke) ermittelte
Worst-Case-Speicherbedarf meist ein Vielfaches größer als die
tatsächlich gespeicherte Datenmenge, d.h. der tatsächlich nutzbare
Anteil des Gesamtspeichers ist ziemlich gering. Praktische Test
erwecken oft den Eindruck, dass man den Speicher deutlich besser
nutzen kann, manchmal sogar zurecht. Aber wer garantiert, dass ein
Speicherproblem durch eine unwahrscheinliche Verkettung unglücklicher
Umstände nicht erst nach Monaten auftritt?
Hier im Forum tauchte einmal die Frage auf, wie man Stackbedarf von
C-Programmen abschätzt. Das ist auch schon schwierig, da aber die
Daten auf dem Stack "dicht" liegen, ist eine (ggf. nicht ganz
optimale) Worst-Case-Abschätzung noch ganz gut machbar.
Auch eine Heap-Verwaltung kann halbwegs überschaubar sein, wenn man
nicht einen universellen Algorithmus benutzt, sondern einige
Einschränkungen in Kauf nimmt.
Beispiel:
In grauer Vorzeit gab es eine Programmier- und Laufzeitumgebung namens
UCSD Pascal. Dort wurde der Heap wie ein Stack, also mit dichtliegen-
den Daten, verwaltet, es gab also keine Speicherfragmentierung. Da der
Heap von unten nach oben und Programmstack von oben nach unten wuchs,
konnte der Speicher wirklich bis aufs letzte Byte gefüllt werden,
bevor der Crash kam. Nachteil: Der Speicher konnte nur in umgekehrter
Reihenfolge der Allozierung wieder freigegeben werden. Die Abschätzung
des Platzbedarfs ist in diesem Fall nicht schwieriger als beim
Programmstack.
Anderes Beispiel:
Bei einfachen Anwendungen benötigt man vielleicht eine oder mehrere
dynamische verkettete Listen, deren Elemente aber alle die gleiche
Größe haben. In diesem Fall kann man sich eine einfache und sehr
effiziente Speicherverwaltung selber bauen: Man legt ein Array mit der
maximal zu erwartenden Anzahl von Elementen an. Die genutzten Elemente
werden entsprechend ihrer Reihenfolge in den Listen verzeigert, die
ungenutzten Elemente ebenfalls. Jedesmal, wenn ein neues Element
benötigt wird, wird einfach das erste Element der Ungenutzt-Liste in
eine der anderen Listen umgehängt, beim Freigeben eines Elements kommt
es zurück in die Ungenutzt-Liste. Die dabei enstehende Fragmentierung
ist unschädlich, weil auf Grund der einheitlichen Elementgröße jede
entstehende Lücke garantiert wieder genutzt werden kann. Da Allozieren
und Freigeben beide in konstanter Zeit ausgeführt werden, ist dieses
Verfahren sogar hart echtzeitfähig.
Ok, wahrscheinlich werden die meisten Standard-Speicherverwaltungen
bei Beschränkung auf gleichgroße Datenblöcke ähnlich gut
funktionieren. Um dessen sicher zu sein, muss man die verwendeten
Algorithmen aber erst analysieren.
Jörg Wunsch wrote:
> p.s.: Mein Lieblingsvergleich von malloc zu statischer Belegung ist der> zwischen Ethernet und Token Ring. Der Token Ring ist die ,,reine> Lehre'': alles ist deterministisch, und bis das Medium wirklich> komplett gesättigt ist, geht alles ganz geregelt seinen Gang. Bei> Ethernet werden Dinge dem Zufall überlassen, und ab 95 % Auslastung> bricht es dann langsam ein. Nur: für die 5 %, die man den Token Ring> dann noch besser benutzen kann, bezahlt man halt einen viel höheren> Preis, da die ganze Verwaltung aufwändig ist. (Und wenn man die 100 %> erreicht hat, muss man sich auch dort dann nach mehr Ressourcen> umsehen.)>> Welches der beiden Protokolle überlebt hat, ist mittlerweile ja> ziemlich klar...
Sei mit solchen Vergleichen lieber vorsichtig... ich hab hier noch ein
Token am kreisen ;).
Die "Verwaltung" ist bei TokenRing viel einfacher als bei switched
Ethernet, die MAU braucht nichtmal Strom! Da drinnen sitzen nur ein paar
ordinäre Relais, die von den NICs geschaltet werden.
Bei Ethernet brauchst du in den Switches dagegen haufenweise Hardware
und Prozessoren, um ähnlich gute Eigenschaften wie Tokenring zu
erreichen. Bei Ethernet ohne switch (hub oder bnc) stößt du bei mehreren
Teilnehmern schon bei 30% der Bruttodatenrate an die Kapazitätsgrenzen -
mit Außreißern in den Latenzzeiten jenseits von gut und böse.
16mbit TokenRing hängt bei vielen Teilnehmern problemlos 100mbit
Ethernet ab, wenn mit Hub statt Switch. Und so'n 30port Switch gibt's
auch net für lau, TokenRing MAUs kannst du dagegen ohne negative
Auswirkungen kaskadieren (ok, Hubs auch, Switches macht nur über Uplink
Port mit >>100mbit Sinn).
I_ H. wrote:
> 16mbit TokenRing hängt bei vielen Teilnehmern problemlos 100mbit> Ethernet ab, wenn mit Hub statt Switch.
Sorry, aber das ist Quark. Ein Ethernet bricht irgendwo bei 95 %
der Bruttodatenrate ein, davor läuft es einfach nur. Ich habe lange
genug mit 10Mbit-Netzen gearbeitet, die bringen problemlos ihre
Datenrate.
Seit 100 Mbit/s wird Ethernet prinzipiell geswitcht. OK, da gibt
es auch Unterschiede in der Qualität, die sich insbesondere im
Gesamtdurchsatz unterscheiden dürften, aber für die 10 Kröten eines
China-Billigswitches gab's beim TokenRing noch nicht mal das Token. ;-)
yalu wrote:
> Bei der üblichen Heap-Verwaltung ist auf Grund der Speicherfragmentie-> rung der theoretisch (über beliebig verteilte Datenblöcke) ermittelte> Worst-Case-Speicherbedarf meist ein Vielfaches größer als die> tatsächlich gespeicherte Datenmenge, d.h. der tatsächlich nutzbare> Anteil des Gesamtspeichers ist ziemlich gering.
Da du nach eigenen Behauptungen malloc() auf einem Controller noch
nie benutzt hast, würde ich dir hier einfach mal die Kompetenz
abstreiten. Sicher kannst du einen pathologischen Fall konstruieren,
in dem das eintreten könnte, allerdings ist es dann die Frage, wie
viel wahrscheinlicher es ist, dass deine ganze Controllerapplikation
bspw. auf Grund eines Hardwarefehlers den Bach vorher runtergegangen
ist.
Nein, 100mbit Ethernet wird nicht immer geswitched, und nein, bei vielen
Teilnehmern und einem zusammenhängenden Ethernet (Hub, kein Switch),
bricht die Datenrate schon sehr weit vor 100% zusammen. Glaub's, es ist
so. 95% könnte bei switched Ethernet der Fall sein, da hast du ja auch 2
Teilnehmer pro Kanal, die beide gleichzeitig losplappern können.
Hubs benutzt man stellenweise auch heute noch, weil die Latenzzeiten
deutlich niedriger als bei switched ethernet sind.
http://www.tu-chemnitz.de/informatik/RA/news/stack/kompendium/vortraege_97/ethernet/performance.html
"Bei 100Base-T ist ab einer Netzlast von 30 % mit einem massiven Anstieg
der Antwortzeiten zu rechnen. Als Netzkonfiguration sind bei den
Anwendungen Textverarbeitung und EMail bis zu 100 PCs und Drucker pro
Ethernet-Segment akzeptabel; bei CAD/CAM max. 15 Stationen je Segment;
bei Videokonferencing, 3D-Simulation, Multimedia max. 4 Stationen. - In
der Praxis stehen höchstens 40 % der physikalischen Bandbreite zur
Verfügung. (Vgl. Gateway 5/97: 42))"
Der Anstieg der Latenz selbst wird von der TCP-Schicht normalerweise
ausgeglichen. Auf unseren DSL-Leitungen haben wir auch deutlich
größere Latenzen als seinerzeit auf ISDN, willst du deshalb zu ISDN
zurück?
Die genannten Maximalzahlen beziehen sich auf den erzielbaren
Gesamtdurchsatz, ist natürlich klar, wenn du CAD/CAM-Anwendungen
(die vor 10 Jahren wohl auf einem Server gegen ein X-Terminal o.ä.
liefen) hast, die viel Grafik übers Netz schaufeln, dann ist das
Netz damit einfach gesättigt. Das wäre aber dein toter Ring auch
(und dessen ,,schnelle'' 16-Mbit/s-Variante wäre sogar schon bei
der Hälfte der 30 % Last dicht, bei der bei dem 100-baseT gerade
mal die Latenz größer wird).
In der heutigen Welt ist das wohl vergleichbar mit 10 Windows-
Terminals, die alle gegen einen WinNT-Terminalserver laufen (aber
nicht Citrix nehmen, die haben es nämlich deutlich intelligenter
implementiert als X11).
@Jörg Wunsch
> Der Anstieg der Latenz selbst wird von der TCP-Schicht normalerweise> ausgeglichen. Auf unseren DSL-Leitungen haben wir auch deutlich> größere Latenzen als seinerzeit auf ISDN, willst du deshalb zu ISDN> zurück?
ja, manchmal schon. Warum lassen denn so viele leute speedpath auf der
DSL-Leitung schalten?. Warum kommt denn VoIP mit der Sprachqualität
nicht auf ISDN Qualität?. Bei DSL geht die latenz ja noch, bei UMTS und
GRRS ist es nicht mehr schön über ssh zu arbeiten. War nicht in einer
der Letzten CT's ein artikel über Industie-Ethernet dort ist auch das
Hauptproblem die Latenz. Die Bandbreite ist heute wirklich nicht mehr
das Problem aber eine geringe Latenz nicht so einfach zu erreichen.
Warum verschicken wir nicht unsere Daten nicht mit der Post(auf
Festplatte) die Bandbreite ist doch dann auch sehr gut? (2Tage laufzeit,
1Tbyte = 5Mbyte/s)
Peter wrote:
> Warum kommt denn VoIP mit der Sprachqualität> nicht auf ISDN Qualität?
Weil die Anforderung voice nun einmal garantierte Bandbreite braucht,
und die gibt's ohne QOS einfach nicht. Andersrum wieder hatte man
bei ISDN mehr oder weniger vergessen, ein Protokoll ohne
Bandbreitengarantie vorzusehen (nicht ganz, man hatte es nur als
Zugang zu einem PAD vorgesehen), damit hast du bei der Benutzung
für IP immer die volle Bandbreite bezahlt, egal ob du sie genutzt
hast oder nicht.
Ja, die Latenz spielt bei Telefonie auch eine Rolle, aber bei
vielen hochbandbreitigen Computerdaten nicht, und eine Bevorzugung
interaktiver Dienste gab's in Form von IPTOS auch schon lange.
Und nein, ohne QOS mag ich VoIP nicht haben, zumindest nicht als
Ersatz für ein normales Telefonnetz.
Aber das schweift nun mächtig vom Thema malloc ab...
Und an der Aussage, dass Tokenring ggü Ethernet doch einige Vorteile
hat, ändert sich auch nix. Es geht ja nicht nur um Latenzen (da hat es
mal ganz sicher Vorteile), sondern auch um Bandbreite - der Link oben
erzählt, dass mehr als 40% Brutto_bandbreite_ in einem unswitched
Ethernet nicht drinnen ist, und so ist es nunmal, denn solange mehrere
Geräte durcheinanderquatschen werden keine Daten übertragen. Bei
TokenRing erreicht man praktisch immer volle Bandbreite, auch bei 100
Rechnern.
Gescheitert ist TokenRing aus ganz anderen Gründen, IBM hatte in der
Vermarktung noch nie ein gutes Gespür, siehe OS/2. Es gibt übrigens auch
100mbit TokenRing.
So - fertig mit dem Thema.
Jörg Wunsch schrieb:
> Da du nach eigenen Behauptungen malloc() auf einem Controller noch> nie benutzt hast, würde ich dir hier einfach mal die Kompetenz> abstreiten.
Sollte hier statt "Kompetenz" nicht eher "Wagemut" stehen? Bin ich
inkompetent, wenn mich weigere, einen (hypothetischen) Revolver mit
einer Million Kammern, von denen eine einzige geladen ist, an meinem
Kopf abzudrücken, obwohl die Wahrscheinlichkeit, dass ich dabei über'n
Jordan gehe, praktisch vernachlässigbar ist?
> Sicher kannst du einen pathologischen Fall konstruieren, in dem das> eintreten könnte,
Schon mal was von Herrn Murphy gehört? Der konstruiert gerne solche
Fälle ;-)
> allerdings ist es dann die Frage, wie viel wahrscheinlicher es ist,> dass deine ganze Controllerapplikation bspw. auf Grund eines> Hardwarefehlers den Bach vorher runtergegangen ist.
Kannst du denn diese Frage beantworten? Ich nicht.
Kurzum: Es widerstrebt mir eben, bewusst Konstrukte in ein Programm
einzubauen, von denen ich sicher weiß, dass sie nur wahrscheinlich
funktionieren. Vor allem dann, wenn es Alternativen gibt, die diesen
Schönheitsfehler nicht haben.
Aber vielleicht bin ich ja nicht nur inkompetent, sondern auch
paranoid :)
I_ H. wrote:
> der Link oben> erzählt, dass mehr als 40% Brutto_bandbreite_ in einem unswitched> Ethernet nicht drinnen ist, ...
Und genau das ist Humbug. Ich habe wirklich lange genug mit alten
10-Mbit/s-Ethernets gearbeitet und dort regelmäßig mit > 1 MiB/s
zu tun gehabt -- ob du das nun glaubst oder nicht. Nein, Switches
hatte es da nicht, das war alles noch RG-58-Verkabelung.
Dass viele PC-Ethernetkarten auf einem ISA-Bus damals diese
Bandbreite nicht geschafft haben, ist ein anderes Thema, aber das
lag nicht am CSMA/CA-Verfahren von Ethernet.
@Jörg Wunsch
> Weil die Anforderung voice nun einmal garantierte Bandbreite braucht,> und die gibt's ohne QOS einfach nicht
Ich weiss Offtopic g
Leider ist QOS auch keine Lösung, denn was hilft es wenn ein Bandbreite
von z.b. 1Mbyte/s garantiert wird aber die packete 1sec lang verzögert
werden? Jitter ist das größte Problem. Und das kann leider auch QOS
nicht verhindern, dann wenn es einmal ein packet auf die reise schickt
und es ist sehr gross dann wartet auch das wichtigere Packet erstmal.
QOS ist für Video über Ehternet OK, dann sieht man zwar das bild etwas
später aber ohne ruckler, aber für VoIP ist Latenz entscheident und das
kann einem leider niemand in einen "echten" netzt aus vielen Routern und
Switchs garantieren.
Soweit ich es noch weiss ist das gernerell ein problem von Netzten was
sich selber organisiert. In Netzten wie Tokenring, ATM, ISDN kann man
genau die Latenz vorhersagen und das ganze ohne QOS.
yalu wrote:
> Kurzum: Es widerstrebt mir eben, bewusst Konstrukte in ein Programm> einzubauen, von denen ich sicher weiß, dass sie nur wahrscheinlich> funktionieren. Vor allem dann, wenn es Alternativen gibt, die diesen> Schönheitsfehler nicht haben.
Die sind aber allesamt teurer: du musst Speicher ,,für alle Fälle''
reservieren (und dir trotzdem noch einen Kopf machen, wie du den
Rückzug antrittst, wenn eines Tages ,,mehr als alle Fälle''
gefordert werden). Wenn du N voneinander unabhängige Ereignisse
hast, must du für alle N Ereignisse jeweils den Maximalplatz
,,für alle Fälle'' reservieren -- nur für den Fall, dass alle N
Ereignisse gleichzeitig auftreten könnten.
Sicherheit war und ist einfach teuer. Wann immer man Sicherheit
durch eine ausreichende Wahrscheinlichkeit ersetzen kann, kann man
wesentlich billiger werden. Das ist mehr als eine Frage nach einem
,,Schönheitsfehler''. Wenn die Wahrscheinlichkeit, dass alle
Ereignisse gleichzeitig auftreten, Größenordnungen geringer ist als
die, dass in deiner Schaltung ein Elko in die Luft fliegt und die
Schaltung sowieso nicht mehr geht, hast du mit der teureren Variante
einfach nur verschwendet. Das ist sicher OK, wenn davon ein
Menschenleben abhängen kann. Wenn davon aber nur noch abhängt, ob
ein Funkthermometer einen Messwert in der Anzeige auslässt, dann
wird es sehr viel sinnvoller sein, sich für die preiswertere Variante
zu entscheiden.
(In meinem Falle ist es etwas anders: die malloc-Variante war einfach
überschaubarer zu implementieren und dadurch mit sehr viel weniger
Aufwand bugfrei zu bekommen. Speicher ist ohnehin genug da, als dass
ich meine nicht vorhandene Perücke darauf verwetten kann, dass der
hier nie ausgehen wird.)
Oh mensch... mit 3 Rechnern hab ich auch 1MB/sek geschafft, das machen
auch ISA Karten (der ISA Bus gibt weit mehr als 1MB/sek her, und wenn du
nicht die billigste Ethernetkarte nimmst...). Mit 100 Rechnern hast du
aber, wenn jeder Rechner die Leitung gleich belastet, in einem 10MBit
unswitched ethernet nur noch 3kb/s pro Rechner (oder noch weniger). Mit
Tokenring 16MBit sind's dann vll 15kb/s.
Nu überleg mal was besser ist... auf dem Papier steht 10MBit vs. 16MBit,
in der Praxis ist TR 5mal so schnell.
Btw. GOTO benutze ich auch nicht wirklich, obwohl es stellenweise sehr
sinnvoll ist.
Peter wrote:
> Leider ist QOS auch keine Lösung, denn was hilft es wenn ein Bandbreite> von z.b. 1Mbyte/s garantiert wird aber die packete 1sec lang verzögert> werden? Jitter ist das größte Problem.
Ja, aber eine ganz andere Baustelle.
Lange Latenzen gibt's auch bei bislang bereits für Telefonie
benutzten Protokollen -- denk nur an Satellitenübertragungen. Die
sind auf jeden Fall störend, haben aber nichts mit stochastischen
Methoden beim Medienzugriff zu tun (um die es ja anfangs mal ging).
> Soweit ich es noch weiss ist das gernerell ein problem von Netzten was> sich selber organisiert.
Naja, welches IP-Netz organisiert sich heutzutage kurzfristig selbst?
Langfristig ja, aber kurzfristig (sodass man sich mit Jitter
rumschlagen müsste) ist da bei den Weitstrecken kein Unterschied zu
bspw. ATM.
ATM hat mir vor vielen Jahren mal jemand aus der Szene beschrieben als
,,für IP ungeeignet, weil die Zellen zu klein sind und für Telefonie
ungeeignet, weil die Zellen zu groß sind''. ;-)
Lernt doch mal zu unterscheiden zwischen latenzbedingtem
Bandbreitenverlust, und Bandbreite die durch Kollisionen verloren gehen.
Das eine kann man mit darüberliegenden Techniken vermeiden, das andere
nur über Switches. Dafür hat man die Dinger erfunden, sind viele NICs an
einer Leitung steigt die Zahl der Kollisionen irgendwann sprunghaft an,
und die Bandbreite geht dementsprechend sprunghaft in die Knie.
Das ist nunmal einfach eine Eigenschaft von Ethernet, die Arbitrierung
ist zwar einfach, aber einfach mal "Hier!" schreien und warten ob
jemanden unterbrochen wurde ist eben einfach mal nicht effizient.
I_ H. wrote:
> Oh mensch... mit 3 Rechnern hab ich auch 1MB/sek geschafft, das machen> auch ISA Karten (der ISA Bus gibt weit mehr als 1MB/sek her, und wenn du> nicht die billigste Ethernetkarte nimmst...).
Auch mit 10 Rechnern, wenn sie nicht gerade alle gleichzeitig das
Medium mit voller Datenrate belegen wollen.
Klar, den Vorteil, bei voll ausgelastetem Medium die Last gleichmäßig
zu verteilen, habe ich dem TR schon ganz oben eingeräumt. Allerdings
ist eine 100%ige Auslastung des Mediums auch nicht der Regelfall
(oder zumindest nicht der wünschenswerte Fall).
Sowie die Auslastung unter 90 % runtergeht, hat der TR aber keinen
Vorteil mehr.
Zurück zum malloc: wenn du den Speicher statisch aufteilst, kannst
du vorhersagen, welcher Teil wann in die Röhre guckt und keinen
mehr bekommt. Da im Normalfall jedoch nicht alle Speicheranforderungen
verschiedener unabhängiger Bedürftiger gleichzeitig erfolgen, ist die
gesamte Speicherauslastung damit schlechter: du reservierst Speicher
für Ereignis B, das im Moment gerade gar nicht anliegt, während
Ereignis A leer ausgeht, da es seine statische Zuweisung erreicht
hat. Bei dynamischer Vergaben könnte A jetzt trotzdem weiterarbeiten
bis zu dem Punkt, da die Summe aus A und B die Gesamtgrenze erreicht.
(OK, Fragmentierung beim simplen malloc-Prinzip führt zu
vorzeitiger Ressourcenverringerung. Könnte man durch handle-
basierte Alternativen aber umgehen, bei denen man im Falle der
Ressourcenknappheit eine garbage collection durchführt.)
Verstehst du absichtlich nicht, was ich schreibe?
Ethernet 10mbit: 1.25MB/s brutto
TR 16mbit: 2MB/s brutto
Nimm dir ein großes Netz wo alle Rechner irgendwie Daten schaufeln. Ein
paar regelmäßig wenig (zB. Internetseiten), ein paar etwas mehr. Dann
schaufeln alle Rechner zusammen bei
Ethernet 10mbit: 30..40% der Bruttorate = 375..500kb/sek, bei
TR 16mbit: 1.8MB/s
Du erreichst bei Ethernet keine 90% Auslastung!!! Bei 30..40% ist
schluss! Und 30..40% Netzauslastung sind ja wohl schon Regelfall!
Wenn du also ein Netz mit 50 Rechnern machen willst, bei dem insg. 1MB/s
möglich sein soll, ist 10MBit Ethernet zu langsam! Wie schon gesagt
sinkt die Bandbreite bei Ethernet sprunghaft, also ab einer bestimmten
Rechnerzahl nimmt die maximal mögliche Bandbreite rapide ab! (wenn 3/4
nicht grad ausgeschaltet sind)
Jörg Wunsch schrieb:
> Die sind aber allesamt teurer: du musst Speicher ,,für alle Fälle''> reservieren (und dir trotzdem noch einen Kopf machen, wie du den> Rückzug antrittst, wenn eines Tages ,,mehr als alle Fälle''> gefordert werden). Wenn du N voneinander unabhängige Ereignisse> hast, must du für alle N Ereignisse jeweils den Maximalplatz ,,für> alle Fälle'' reservieren -- nur für den Fall, dass alle N Ereignisse> gleichzeitig auftreten könnten.
Wenn tatsächlich der Fall eintreten kann, dass alle N Ereignisse
gleichzeitig den Worst-Case an Speicherplatz unbedingt benötigen,
sollte man meiner Meinung nach für diesen Fall gerüstet sein.
Es gibt sicher Fälle, wo man Kompromisse eingehen kann:
Ein klassisches Beispiel sind Büroanwendungen. Die werden halt neu
gestartet, wenn sie gecrasht sind oder eine Speicher-Voll-Meldung
erscheint, da hat sich schon jeder daran gewöhnt.
Ein anderes Beispiel sind Haushaltsgeräte, Messgeräte u.ä., die immer
nur für eine gewisse Zeit in Betrieb sind und bei jedem Einschalten
resettet werden.
Bei einem Gerät, das ständig in Betrieb ist, würde ich diesen
Kompromiss nicht eingehen, egal ob sicherheitskritisch oder nicht. Vor
allem bei fest installierten und schwer zugänglichen Geräten macht es
keinen Spass, sich alle paar Wochen zu einem (möglicherweise aus
Kostengründen nicht einmal existenten) Resetknopf vorzukämpfen, um das
Gerät nach einem Fehlverhalten wieder in einen definierten
Ausgangszustand zu versetzen.
Zur letzten Kategorie zähle ich auch den im Freien installierten
Sensor- und Sendeteil des von dir angesprochenen Funkthermometers,
sofern sich darin ein Mikrocontroller verbirgt.
(Langweilig inzwischen, daher meine letzte Äußerung dazu.)
I_ H. wrote:
> Verstehst du absichtlich nicht, was ich schreibe?>> Ethernet 10mbit: 1.25MB/s brutto> TR 16mbit: 2MB/s brutto
Ja. Allerdings hättest du hier gegen TR 4 Mbit/s vergleichen müssen,
denn die waren ungefähr zur gleichen Zeit da.
> Du erreichst bei Ethernet keine 90% Auslastung!
Dann bleib bei deinem Glauben. Ich weiß, dass man die 90 %
Auslastung locker erreicht, ich habe das selbst zu 10-Mbit/s-Zeiten
genügend gehabt. Und nein, wir hatten nicht nur einen Rechner da
dran, und wir hatte -- wie ich dir ebenfalls schon geschrieben
habe -- keinen Switch, da das alles noch zu Zeiten von 10base2 war.
Im einzigen TR-16-Netz, an dem ich jemals mit dabei war (das dort mehr
aus politischen Gründen noch existierte, es muss wohl mal irgendwann
eine ,,strategische Entscheidung'' der Obrigkeit gewesen sein), war
jeder heilfroh, wenn er zu den privilegierten gehörte, die parallel
dazu noch eine 100-Mbit/s-Ethernetkarte besitzten durfte. Das war
nämlich ein Unterschied wie Porsche zu VW Käfer. Dabei war jedoch
aus besagten politischen Gründen die Einführung dieser Netzwerktopologie
dort über Jahre verzögert worden. Mittlerweile ist auch dort der tote
Ring tot.
yalu wrote:
> Wenn tatsächlich der Fall eintreten kann, dass alle N Ereignisse> gleichzeitig den Worst-Case an Speicherplatz unbedingt benötigen,> sollte man meiner Meinung nach für diesen Fall gerüstet sein.
Dann bist du halt wieder teurer.
Es gibt eine gewisse Wahrscheinlichkeit von > 0, dass die vor dir
liegende Computertastatur plötzlich ,,von allein'' ein paar cm
nach oben springt. Trotzdem ist das halt so unwahrscheinlich, dass
wir dafür keine Vorkehrungen treffen. Wir treffen selbst für viel
wahrscheinlichere Ereignisse wie ein Erdbeben keine Vorkehrungen,
weil man zwar erdbebensicher bauen könnte, das aber gemessen an
der geringen Wahrscheinlichkeit billiger ist, die Schäden nach einem
solchen zu reparieren als von vornherein so zu bauen.
> Bei einem Gerät, das ständig in Betrieb ist, würde ich diesen> Kompromiss nicht eingehen, egal ob sicherheitskritisch oder nicht. Vor> allem bei fest installierten und schwer zugänglichen Geräten macht es> keinen Spass, sich alle paar Wochen zu einem (möglicherweise aus> Kostengründen nicht einmal existenten) Resetknopf vorzukämpfen, um das> Gerät nach einem Fehlverhalten wieder in einen definierten> Ausgangszustand zu versetzen.
Das würde ich dann auch unter Fehldesign einsortieren. Wenn dynamische
Anforderungen auftreten, muss man auch mit dem Zustand der ggf. mal
nicht vorhandenen Ressourcen klar kommen (egal, ob man diese per
statischer Tabelle alloziert hat und Nmax doch zufällig mal über-
schritten wird, oder ob man sich für dynamische Allozierung
entschieden hat). Damit meine ich nicht, dass man Windowsmäßig es
dem Nutzer zumutet, dann den Resetknopf zu drücken. ;-) Gerade im
Controllerbereich gibt es ja durchaus andere Möglichkeiten, und sei's
ein ,,Fallrückzieher'' über einen Watchdog-Reset.
> Dann bist du halt wieder teurer.
Das mit den Kosten halte ich für kein gutes Argument. Die sicherere
Variante eines Algorithmus reserviert zwar mehr Platz für Daten, um
alle vorkommenden Fälle abzudecken und benötigt entsprechend viel RAM.
Bei der malloc-Variante belegen die Daten zwar weniger Speicher, weil
die unwahrscheinlichen Fälle, in denen diese Speichermenge nicht
ausreicht, einfach ignoriert werden. Jedoch muss zusätzlicher Speicher
vorgesehen werden
1. für Verwaltungsinformationen )mindestens ein size_t für jeden
allozierten Speicherblock)
2. für die durch Speicherfragmentierung entstehende, nicht nutzbare
Lücken
3. etwas Reserve, falls Die Wahrscheinlichkeit des Eintretens des
unwahrscheinlichen Ereignisses doch größer ist als erwartet
Es hängt sicher von der jeweiligen Anwendung ab, wieviel zusätzliches
RAM diese drei Punkte tatsächlich erfordern, aber ignorieren kann man
sie i.Allg. nicht:
Punkt 1 ist nur dann vernachlässigbar, wenn man nur ganz wenige, sehr
goße Speicherblöcke alloziert. Dafür gibt es aber meist bessere
Methoden als das klassiche malloc.
Punkt 2 ist nur dann vernachlässigbar, wenn alle allozierten
Speicherblöcke die gleiche Größe haben. Auch dafür gibt es wesentlich
bessere Alternativen zu malloc (s. mein erster Beitrag in diesem
Thread). Diese sparen sogar CPU-Zeit und Programmspeicher (wo wir
schon von den Kosten reden ;-)).
Punkt 3 ist nur dann vernachlässigbar, wenn man die Wahrscheinlichkeit
des Versagens der Methode hinreichend genau ermitteln kann und diese
W. kleiner als die W. sonstiger Fehlerursachen, bspw. von
Hardwareausfällen, ist. Das zu entscheiden dürfte aber beliebig schwer
sein.
Deswegen ist malloc ist in meinen Augen ausschließlich dafür geeignet,
die Programmierung zu vereinfachen und damit Entwicklungskosten, nicht
aber Hardwarekosten einzusparen.
Für komplexe PC-Anwendungen, wo aufgrund riesiger RAM-Mengen alle drei
der genannten Punkte kein Thema sind, ist malloc ok, ebenso bei
Mikrocontrolleranwendungen mit geringen Stückzahlen, wo die
Entwicklungskosten wichtiger als die Hardwarekosten sind.
Für weniger komplexe Mikrocontrolleranwendungen mit hohen Stückzahlen
muss sehr genau abgewägt werden, ob man mit malloc tatsächlich
RAM-Bytes sparen kann. Ich würde sagen, in der Mehrheit der Fälle
nicht.
Dadurch, dass die Ausfallswahrscheinlichkeit auf Grund unerwartet
hoher Speicherfragmentierung nur sehr schwer abschätzbar ist, besteht
zusätzlich das Risiko, dass das Produkt bei einer größeren Zahl der
Kunden unzuverlässig arbeitet. Es dürfte klar sein, dass die dann
enstehenden Kosten in einer ganz anderen Größenordnung liegen als die
paar RAM-Bytes, um die wir gerade diskutieren :)
> Gerade im Controllerbereich gibt es ja durchaus andere> Möglichkeiten, und sei's ein ,,Fallrückzieher'' über einen> Watchdog-Reset.
Du bist wohl auch so einer, bei dem beim Autofahren in der Kurve
ständig die ESP-Lampe blinkt ;-)
yalu wrote:
> Du bist wohl auch so einer, bei dem beim Autofahren in der Kurve> ständig die ESP-Lampe blinkt ;-)
Aber nur wenn seine ESP Elektronik noch genügend Heap für malloc frei
hat..
SCNR :D
Du bringst da was durcheinander, vll hattet ihr doch ein switched
ethernet. Auch 10base2 kann man segmentieren.
Überleg mal warum praktisch jedes verdammte Ethernet heute geswitched
ist, obwohl hubs viel günstiger sind.
Übrigens ist auch GBit Tokenring spezifiziert.
noch was zu malloc vs. statischem speicher:
ich persönlich habe nichts gegen malloc, wenn sein einsatz lokal
begrenzt wird. z.b. hat man auf grösseren µC meistens mehrere
softwarekomponenten, von denen einige, unkritische wegen 'out of memory'
auch mal versagen dürfen, während andere unbedingt immer laufen müssen.
globale nutzung von malloc/free ist ein nicht zu unterschätzendes
risiko, wenn ein relativ unwichtiges modul plötzlich dafür sorgt, dass
wichtigen komponenten der speicher fehlt.
Ich hab ja nichts gegen malloc, bloß ich habs bisher noch nirgends
gebrauchen können.
Wenn ich irgendwelche lokalen Arrays brauche, dann ist deren Größe schon
zur Compilezeit bekannt.
Und die Puffer für CAN, I2C, UART usw. müssen ja global sein (es kann ja
jederzeit was reinkommen / gesendet werden müssen), da nützt malloc auch
nichts.
Dem Scheduler habe ich die maximale Zahl an gleichzeitigen Prozessen
auch schon zur Compilezeit reserviert.
Umsortieren muß ich auch nichts.
Ich habe also das Pech, keinerlei sinnvolle Aufgabe für das malloc zu
haben.
Peter
Ich verstehe nicht ganz das Problem. Es ist doch ganz einfach: Kann man
zur Programmierzeit einschätzen wie viel Speicher benötigt wird (zum
Beispiel eine Tabelle mit X Einträgen) dann macht man es halt statisch.
warum sollte man dann malloc benutzen?
Wenn man allerdings zur Programmierzeit nicht weiß wie viel Speicher
wirklich benutzt wird muss man halt malloc benutzen, das ist doch ganz
natürlich und absolut sinnvoll. In jedem Fall besser als dann z.B. eine
Tabelle statisch zu begrenzen. Wenn eben kein Speicher mehr da ist, dann
muss man diesen Fall halt abfangen und entsprechende Maßnahmen
ergreifen. Zum Beispiel indem der Benutzer eine Meldung bekommt, er
solle doch ein paar Einträge aus der Tabelle löschen, wenn er neue
hinzufügen will. Oder indem weniger wichtige Variablen vielleicht
kurzfristig auf eine SD Karte oder so ausgelagert werden.
Ich sehe absolut kein Sicherheitsrisiko bei malloc. Man muss halt sauber
programmieren und den Fehlerfall sinnvoll abfangen und dann kann man
dank malloc viele Probleme flexibler lösen.
Das einzige Problem mit malloc ist die Sache mit dem Stack, aber auch
hier kann man ja das Problem lösen, indem man nur einen bestimmten
Bereich des Speichers für den heap vorsieht.
Aber vielleicht verkenne ich hier ein Problem. eventuell kann mal jemand
einen hypothetischen Fall erläutern in dem malloc, gegenüber einer
statischen Speichernutzung schwerwiegende Probleme verursachen kann.
> Das einzige Problem mit malloc ist die Sache mit dem Stack, aber auch> hier kann man ja das Problem lösen, indem man nur einen bestimmten> Bereich des Speichers für den heap vorsieht.
wieso mit dem stack? und ja, man muss immer einen RAM-bereich für den
heap reservieren.
> Aber vielleicht verkenne ich hier ein Problem. eventuell kann mal jemand> einen hypothetischen Fall erläutern in dem malloc, gegenüber einer> statischen Speichernutzung schwerwiegende Probleme verursachen kann.
softwarekomponenten A und B sind unabhängig, benutzen aber beide
malloc/free.
A braucht nun temporär sehr viel speicher, jetzt kommt B dran und
bekommt plötzlich 0 von malloc zurück.
piepvogel wrote:
>> Das einzige Problem mit malloc ist die Sache mit dem Stack, aber auch>> hier kann man ja das Problem lösen, indem man nur einen bestimmten>> Bereich des Speichers für den heap vorsieht.>> wieso mit dem stack? und ja, man muss immer einen RAM-bereich für den> heap reservieren.
malloc prüft zwar, ob noch genug Platz ist für den Block, der allokiert
werden soll, ABER der Stack prüft beim Wachsen nicht, ob er in den Heap
reinläuft. Deswegen kann es da Probleme geben...
piepvogel wrote:
> wieso mit dem stack? und ja, man muss immer einen RAM-bereich für den> heap reservieren.
Der Heap wird normalerweise automatisch alloziert. Übrigens ist
ein Vorteil von malloc() gegenüber alloca() bzw. großen Variablen
auf dem Stack, dass bei RAM-Knappheit malloc() fehlschlägt und
eine 0 zurück gibt, während der Stack sich immer Platz macht --
gegebenenfalls halt in die statischen Variablen hinein.
I_ H. wrote:
> Du bringst da was durcheinander, vll hattet ihr doch ein switched> ethernet. Auch 10base2 kann man segmentieren.
Aber Switches gab's da nicht, nur Repeater. Das einzige Problem, was
diese gelöst haben war, dass ein kaputter Terminator nur einen Strang
lahm gelegt hat, nicht das ganze Netz. Ansonsten hat man den
kompletten Traffic des gesamten Netzes gesehen -- ich habe tcpdump
oft genug benutzen dürfen zu dieser Zeit...
> Überleg mal warum praktisch jedes verdammte Ethernet heute geswitched> ist, obwohl hubs viel günstiger sind.
Weil man mit einem hochwertigen Switch halt nochmal ein vielfaches
der Bandbreite des Einzelkabels erreichen kann. Damit hat man
praktisch eine Konstellation, als hätte man N einzelne Netze jeweils
zwischen den gerade kommunzierienden Maschinen, jede mit voller
Bandbreite.
Weil die Technologie, ein Ethernet zu switchen, seit 100baseTX so
preiswert geworden ist, dass du sie für einen Appel und ein Ei selbst
bei dir zu Hause einsetzen kannst. (Einen Bandbreitengewinn würde
ich davon aber nicht erwarten.) Es gibt praktisch keine Hubs mehr.
Der Chinaswitch kostet gerade mal noch so viel, wie die Relais für
einen TR-Port im MAU wohl mal gekostet haben werden. Die gab's
nämlich auch nicht umsonst, und anders als bei dicken Halbleitern
sinkt deren Preis auch nicht unendlich, wenn man nur genügend davon
anfertigen lässt.
Weil man mit einem managed switch weit mehr machen kann: VLANs,
Ports einzeln konfigurieren (ggf. auch aus der Ferne), Port
security bis hin zu kryptografischer Authentisierung, ...
Schonmal dran gedacht, dass man mit einem Rechner ein 10base2
segmentieren kann? 2 NICs rein, bridge einrichten, fertig. Macht bei
10base2 in jedem Fall Sinn, eben wegen den Kollisionen.
Dazu braucht man nichtmal einen Rechner, gibt genug Router die sowas
können, und auch die nötige Hardware on board haben (zB. Cisco).
Also du kannst erzählen was du willst, es ist allgemein bekannt und ich
hab selber auch schon erlebt, dass man mit 10base2 bzw. unswitched
ethernet bei weitem nicht die volle Bandbreite erreicht, wenn mehrere
Rechner dranhängen.
Das ist einer der Hauptgründe wieso Switches eingeführt wurden, die
billigen haben intern auch nicht viel mehr als 100mbit Bandbreite.
piepvogel wrote:
>> Aber vielleicht verkenne ich hier ein Problem. eventuell kann mal jemand>> einen hypothetischen Fall erläutern in dem malloc, gegenüber einer>> statischen Speichernutzung schwerwiegende Probleme verursachen kann.>> softwarekomponenten A und B sind unabhängig, benutzen aber beide> malloc/free.> A braucht nun temporär sehr viel speicher, jetzt kommt B dran und> bekommt plötzlich 0 von malloc zurück.
Ja aber, das sehe ich halt nicht als Problem, sondern eben gerade als
Stärke von Malloc, das man hier völlig flexibel darauf reagieren kann.
Je nach Anwendung gibt man nun den Nutzer eine Meldung, das die Aktion X
nicht möglich war, da zum Beispiel in der Tabelle Y zu viele Einträge
sind. der Nutzer kann nun entscheiden ob er die Einträge in der Tabelle
Y reduziert und dafür X machen kann oder ob er X sein lässt. Falls der
Prozessor automatisch läuft kann man ja einen teil des speicher
auslagern oder die unwichtige Anwendung B selbst ein wenig stutzen oder
A halt nicht ausführen oder warten bis wieder genug speicher frei ist.
Man ist halt absolut flexibel was die Behandlung des Fehlers angeht und
je nach Priorität kann man das problem dann so oder so lösen oder die
Lösung sogar dem Nutzer überlassen... besser gehts doch gar nicht oder?
Die Messungen gehen halt leider nur bis 25 Rechner, aber da sieht man
schon wie sich das entwickelt. Bei großen Paketen steigt die Latenz um
Faktor >4 vgl. mit 5 Rechnern, und bei kleinen Paketen bleiben noch
8.5mbit Bandbreite übrig.
Der Effekt der geringeren Bandbreite schaukelt sich mit mehr Rechnern
immer weiter auf. Denn wenn ein Rechner einmal nicht senden konnte, muss
er's nochmal versuchen. Bei kleinen Paketen und 1mbit Datenrate werden
bei 50% Kollisionen glaub effektiv >2mbit belegt. Die neu übertragenen
Pakete können ja auch wieder Kollisionen auslösen.
Also bei großen Netzen geht das schnell in die Hose. Der erste Link den
ich gepostet hatte, ging von max. 100 Rechnern aus. Das deckt sich in
etwa mit dem pdf, da wären bei 100 Rechnern und linearem Verlauf noch
4mbit übrig. Leider ist es halt nicht linear. Und wie die Latenzen bei
100 Rechnern aussehen, möcht ich lieber nicht wissen (bei großen Paketen
sicherlich >1s), und was dann noch von den 4mbit übrig bleibt auch
nicht.
Ich hab nun endgültig fertig mit dem Thema.
Was soll dieses Netzwerkgeflame in diesem Thread? Ich möchte hier gerne
was über malloc vs. statische Variablen lesen! Seid ihr denn zum ersten
mal in einem Forum unterwegs? Hier gibts sowas wie Regeln!
>>> Aber vielleicht verkenne ich hier ein Problem. eventuell kann mal jemand>>> einen hypothetischen Fall erläutern in dem malloc, gegenüber einer>>> statischen Speichernutzung schwerwiegende Probleme verursachen kann.>>>> softwarekomponenten A und B sind unabhängig, benutzen aber beide>> malloc/free.>> A braucht nun temporär sehr viel speicher, jetzt kommt B dran und>> bekommt plötzlich 0 von malloc zurück.> Ja aber, das sehe ich halt nicht als Problem, sondern eben gerade als> Stärke von Malloc, das man hier völlig flexibel darauf reagieren kann.> Je nach Anwendung gibt man nun den Nutzer eine Meldung, das die Aktion X> nicht möglich war, da zum Beispiel in der Tabelle Y zu viele Einträge> sind. der Nutzer kann nun entscheiden ob er die Einträge in der Tabelle> Y reduziert und dafür X machen kann oder ob er X sein lässt. Falls der> Prozessor automatisch läuft kann man ja einen teil des speicher> auslagern oder die unwichtige Anwendung B selbst ein wenig stutzen oder> A halt nicht ausführen oder warten bis wieder genug speicher frei ist.> Man ist halt absolut flexibel was die Behandlung des Fehlers angeht und> je nach Priorität kann man das problem dann so oder so lösen oder die> Lösung sogar dem Nutzer überlassen... besser gehts doch gar nicht oder?
das problem dabei ist, wie gesagt, ein modul dem anderen den speicher
wegsaugen kann. eine lösung wäre z.b. zwei getrennte heaps zu benutzen.
auch doof sind sogannte heap crashs, also wenn aus irgendeinem grund
über die 'gemallocte' grenze hinaus geschrieben wurde. in dem fall ist
der heap kaputt und kein nachfolgendes malloc/free/realloc wird
zuverlässig arbeiten. alloca() und das C99 feature 'variable length
arras' sind aber auch gefährlich. verzichtet man auch darauf, können
einem nur noch rekursive funktionen gefährlich werden. wenns um
betriebssicherheit geht, geht oft kein weg an statischem speicher
vorbei. ein compiler kann übrigens zugriffe auf statischen speicher viel
besser optimieren (noch besser, wenn man das keyword 'restrict'
verwendet), allein schon, weil keine zusätzlich indirektion erforderlich
ist, wie bei zugriffen über pointer.
piepvogel wrote:
> das problem dabei ist, wie gesagt, ein modul dem anderen den speicher> wegsaugen kann. eine lösung wäre z.b. zwei getrennte heaps zu benutzen.
Ja, aber wie ich schon oben geschrieben habe, kann man diesen Fehlerfall
dann abfangen und je nach Situation geeignet darauf reagieren um das
Programm zu lösen. Daher sehe ich das nicht als ein Nachteil von malloc,
sondern eben als ein Vorteil, das man auf soetwas flexibel reagieren
kann.
Oft können ja solche Programmierprobleme nicht statisch gelöst werden da
ja am Anfang nicht feststeht welches Modul wie benutzt wird und wie viel
Speicher besetzt. Daher ist es ja gerade schlecht, wenn sich die Module
statisch den Speicher teilen. Wird da dynamisch, je nach Anforderung
gemacht kann der Nutzer das System viel besser nach seinen wünschen
benutzen und stößt nicht so schnell an Grenzen. Stößt er dann doch
einmal an Grenzen, zum Beispiel im Fall wie du ihn geschildert hast,
dann muss man das eben programmtechnisch abfangen.
Also das Problem liegt offensichtlich hier nicht bei malloc, sondern
beim Programmierer der zu faul war das Problem sachgerecht abzufangen.
> auch doof sind sogannte heap crashs, also wenn aus irgendeinem grund> über die 'gemallocte' grenze hinaus geschrieben wurde. in dem fall ist> der heap kaputt und kein nachfolgendes malloc/free/realloc wird> zuverlässig arbeiten.
Das ist aber ein Programmierfehler, wenn so etwas passiert und über eine
statische Arraygrenze kann man ja auch drüber hinwegschreiben. Soetwas
darf ja niemals passieren, egal ob statisch oder dynamisch.
> alloca() und das C99 feature 'variable length> arras' sind aber auch gefährlich. verzichtet man auch darauf, können> einem nur noch rekursive funktionen gefährlich werden.
Diese Probleme sehe ich als viel unberechenbarer und schlimmer als das
von dir oben geschilderte Malloc Program. Da man diese Fehler während
der Laufzeit nicht so günstig abfangen kann, hier schützt nur eine
absolut saubere Programmierung und ne Menge Platz zwischen Stack und dem
Rest des Speichers.
> wenns um> betriebssicherheit geht, geht oft kein weg an statischem speicher> vorbei.
Wie schon eben beschrieben sehe ich das nicht so. Ganz im Gegenteil.
Eine saubere dynamische Speicherlösung kann durch ihre Flexibilität
sogar sicherer sein, da sie im Zweifelsfall für die wirklich wichtigen
Anwendungen alleine Platz schaffen kann bei einer statischen
Speicherlösung hingegen sind Möglichkeiten der Fehlerbehandlung beim
ausgehenden Speicher um ein vielfaches geringer. es ist halt alles nur
eine Frage der sauberen und verantwortungsbewussten Programmierung.
>ein compiler kann übrigens zugriffe auf statischen speicher viel> besser optimieren (noch besser, wenn man das keyword 'restrict'> verwendet), allein schon, weil keine zusätzlich indirektion erforderlich> ist, wie bei zugriffen über pointer.
Ja das kann ich mir gut vorstellen. Ich gehöre ja selbst auch nicht zu
den Programmierern die ständig dynamisch Speicher anfordern. Wenn ich
ein Problem mit statischen Speicher gut lösen kann, dann mache ich das
auch. Aber es gibt nun einmal Fälle wo man dynamisch einfach besser
fährt und wo man dank dynamischen Speicher den Mehrwert einer Anwendung
stark erhöhen kann.
>> das problem dabei ist, wie gesagt, ein modul dem anderen den speicher>> wegsaugen kann. eine lösung wäre z.b. zwei getrennte heaps zu benutzen.> Ja, aber wie ich schon oben geschrieben habe, kann man diesen Fehlerfall> dann abfangen und je nach Situation geeignet darauf reagieren um das> Programm zu lösen. Daher sehe ich das nicht als ein Nachteil von malloc,> sondern eben als ein Vorteil, das man auf soetwas flexibel reagieren> kann.
du kannst den fehler aber nur lokal behandeln. mal ein extrembeispiel
für schlechtes design: während der benutzer eine freundliche nachricht
sieht, dass er gerade zu viele daten eingegeben hat und sich mal etwas
zurückhalten soll, musste der netzwerkstack 1000 empfangene pakete
wegwerfen, weil er keine packetbuffer mehr vom heap bekommt.
>> auch doof sind sogannte heap crashs, also wenn aus irgendeinem grund>> über die 'gemallocte' grenze hinaus geschrieben wurde. in dem fall ist>> der heap kaputt und kein nachfolgendes malloc/free/realloc wird>> zuverlässig arbeiten.> Das ist aber ein Programmierfehler, wenn so etwas passiert und über eine> statische Arraygrenze kann man ja auch drüber hinwegschreiben. Soetwas> darf ja niemals passieren, egal ob statisch oder dynamisch.
in einem projekt von mir steckt eine skriptsprache (compiler und virtual
machine), in der ein benutzer auch arrays anlegen und rekursionen
programmieren kann. das ganze verwendet einen separaten heap. der
benutzer kann durch programmierfehler heap-crashs verursachen.
runtime-checks bei jedem array-zugriff zu machen, wäre zu langsam.
trotzdem führt ein heap-crash nicht zu einem absturz des gesamtsystems,
sondern es wird einfach die skriptausführung abgebrochen und eine
fehlermeldung erzeugt. das ist der vorteil eines lokalen heaps, der nur
von einem modul benutzt wird.