Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Draytek 2920 en IPv6 op glasvezel

473 views
Skip to first unread message

erwin....@gmail.com

unread,
Nov 26, 2012, 4:26:39 AM11/26/12
to
Sinds enige dagen heb ik een Draytek 2920 met nieuwste fw die IPv6 ondersteunt. Helaas lukt het me maar niet om een IPv6-adres op mijn WAN verbinding te krijgen. Bij mijn vorige router (Linksys met Tomato) was dat geen probleem. Ik krijg wel netjes een IPv4-adres op de WAN2.

Ik heb WAN2 op PPPoE staan, en begrepen dat IPv6 dan op PPP moest staan. Helaas werkt dat niet.
Op mijn oude router werkte IPv6 met 'Prefix delegation', dus ik heb op de Draytek ook DHCPv6 client geprobeerd op prefix delegation en dan IAID op 0.
Beiden werken niet.

Heeft iemand een andere suggestie?

Vassilis Aretakis

unread,
Dec 5, 2012, 2:57:50 PM12/5/12
to
Do you have FTTH? and if yes... which linksys you used?

erwin....@gmail.com

unread,
Dec 9, 2012, 7:27:54 AM12/9/12
to
Yes, I do have ftth.
And I used an Linksys E3200, but I don't think that matters. What does matter, is that I still can't get it to work on the Draytek 2920. It should be so easy, as all I have to do should be to set IPv6 on PPP as well, see: http://www.karel.org/newsportal/article.php?id=2265&group=xs4all.ipv6

In the meantime I've tried everything from setting static IP's to, well, every setting there is. All without any result.
It shouldn't be that hard, should it?

erwin....@gmail.com

unread,
Dec 9, 2012, 7:40:41 AM12/9/12
to
All I get are local link addresses on the WAN-port, not a Global IP
IP: FE80::1D:AAFF:FE81:9202/128 (Link)
Gateway: FE80::90:1A00:1A4:1F2

And I can't ping any of those addresses, only the local link address on the LAN sids.

Koos van den Hout

unread,
Dec 10, 2012, 7:20:26 AM12/10/12
to
erwin....@gmail.com wrote in <61cc387f-4ee7-4963...@googlegroups.com>:
> All I get are local link addresses on the WAN-port, not a Global IP
> IP: FE80::1D:AAFF:FE81:9202/128 (Link)
> Gateway: FE80::90:1A00:1A4:1F2

Enige hulp die ik kan geven: het klopt dat de ppp verbinding tussen jou en
xs4all alleen linklocal adressen heeft. Als de prefix delegatie goed werkt
wordt aan de LAN kant van je router ook globaal routeerbaar IPv6
uitgedeeld.

Uit mijn pppd log:

Dec 10 02:39:38 greenblatt pppd[5716]: remote IP address 194.109.5.227
Dec 10 02:39:38 greenblatt pppd[5716]: local LL address fe80::021f:c6ff:fe59:76f6
Dec 10 02:39:38 greenblatt pppd[5716]: remote LL address fe80::0090:1a00:0142:70eb

Koos

--
Koos van den Hout Homepage: http://idefix.net/
PGP keyid DSS/1024 0xF0D7C263
Webprojects: Camp Wireless http://www.camp-wireless.org/
The Virtual Bookcase http://www.virtualbookcase.com/

erwin....@gmail.com

unread,
Dec 10, 2012, 7:42:04 AM12/10/12
to
Okay, dat kan een en ander verklaren (al heb ik toch echt in mijn hoofd dat mijn Tomato-router zelf ook een 'echt' ipv6-adres kreeg).
Dat betekent dus dat het probleem zit aan de LAN-kant: daar krijgen de machines namelijk alleen een link-local ip en dat moet een global link zijn.

Mijn idee is dat de RADVD-service daarvoor moet zorgen: die staat dan ook aan op LAN1 (waar de PC's aan hangen).
DDHCPv6 en Static IPv6 heb ik op LAN1 uitgeschakeld, omdat ik het liefst heb dat de clients een IPv6 krijgen toebedeeld o.b.v. hun MAC-adres en dat gaat volgens mij m.b.v. Router advertisements en dus de RADVD-service. Klopt die redenering?

Miquel van Smoorenburg

unread,
Dec 10, 2012, 9:27:07 AM12/10/12
to
In article <f6b4880c-d806-436b...@googlegroups.com>,
<erwin....@gmail.com> wrote:
>Okay, dat kan een en ander verklaren (al heb ik toch echt in mijn hoofd dat
>mijn Tomato-router zelf ook een 'echt' ipv6-adres kreeg).

Dat moet-ie ook krijgen, maar niet vanzelf, daar moet je wel wat voor doen.
Je router moet aan de WAN (PPP) kant een DHCPv6 client draaien die om een PD
(prefix-delegation) vraagt. Dan krijg je een /48, en daar moet je router
dan zelf een /64 uit kiezen die hij dan aan een ethernet interface aan
de LAN kan toebedeeld. Meerdere /64s als je meerdere LAN poorten hebt.

Mike.

erwin....@gmail.com

unread,
Dec 10, 2012, 11:54:04 AM12/10/12
to
Dan had ik het dus toch wel goed in mijn hoofd ;-)
Op mijn Draytek 2920 heb ik als IPv6 'connection type' zowel DHCPv6-client met prefix delegation geprobeerd, als PPP-client. Helaas krijg ik in geen gevallen een publiek IPv6-adres.
Bij DHCPv6 moet ik echter wel een IAID (Identity Association ID) invullen, maar ik heb geen idee wat dat moet zijn en of dat "uberhaupt wel relevant is. Iemand ervaring met een Draytek 2920 + IPv6?
Een andere goede suggestie is natuurlijk ook altijd welkom :-)

rene...@gmail.com

unread,
Dec 11, 2014, 3:07:59 PM12/11/14
to
Hier werkt het met een Draytek 2925. PPP is goed.

Miquel van Smoorenburg

unread,
Dec 11, 2014, 3:28:53 PM12/11/14
to
In article <6171fae1-05c0-4e36...@googlegroups.com>,
<rene...@gmail.com> wrote:
>Hier werkt het met een Draytek 2925. PPP is goed.

Dat modem doet ook RFC4638, je hebt een MTU van 1500.

Mike.

rene...@gmail.com

unread,
Dec 19, 2014, 11:24:41 AM12/19/14
to
Op donderdag 11 december 2014 21:28:53 UTC+1 schreef Miquel van Smoorenburg:
Oh? Ik had dat laatst gevraagd aan support en die zeiden dat het niet kon.
Via de webinterface kan ik max 1492 instellen.

Rob

unread,
Dec 19, 2014, 12:49:19 PM12/19/14
to
Wellicht negeert hij dat veldje als RFC4638 gesupport wordt.
Werkt je IPv6 naar allerlei sites zonder dat je zelf hoeft te vogelen
aan de MTU op je computers?

Miquel van Smoorenburg

unread,
Dec 19, 2014, 3:31:37 PM12/19/14
to
In article <9f7b6ce9-3a72-48f8...@googlegroups.com>,
Nou, als ik kijk naar je ppp sessie (er even van uit gaande dat je post
vanaf je thuisverbinding) dan zie ik dit:

Logical interface pp0.1073939631 (Index 28693) (SNMP ifIndex 68905)
Flags: Up Point-To-Point SNMP-Traps 0x4000 Encapsulation: PPPoE
PPPoE:
Session AC name: dr11.d12, Remote MAC address: e0:30:05:f1:fc:17,
PAP state: Success
Protocol inet, MTU: 1500, Generation: 409164, Route table: 0
Protocol inet6, MTU: 1500, Generation: 409165, Route table: 0

Maw, een MTU van 1500. Die Juniper liegt niet :) Ook:

$ ping -M do -s 1472 83.161.148.jij
PING 83.161.148.54 (83.161.148.jij) 1472(1500) bytes of data.
1480 bytes from 83.161.148.jij: icmp_seq=1 ttl=252 time=5.64 ms

Ik kan je met 1500 bytes packets pingen.

Ik weet niet welke support gezegd heeft dat het niet werkt, maar
die hebben ongelijk: je MTU is 1500.

Mike.

Rob

unread,
Dec 19, 2014, 3:47:07 PM12/19/14
to
Ik weet niet of dat van jou of van Timo kwam, maar er was al geconstateerd
dat ook Draytek producten waar nog geen RFC4638 support in zit bij jullie
een MTU van 1500 geven, omdat ze kennelijk de MRU niet opsturen als die
niet specifiek ingesteld is en de Juniper dan maar aanneemt dat het 1500
is (bug! de RFC zegt dat het dan 1492 is).

Die MRU kun je wel in de telnet interface instellen maar niet in de web
interface.
Als dit niet gedaan is dan staat er bij jullie 1500 maar dropt hij alles
wat >1492 is, en omdat de Juniper dan niks retour stuurt heb je dan grote
problemen die je alleen weg krijgt door al je interne machines op MTU 1492
te configureren.

Miquel van Smoorenburg

unread,
Dec 19, 2014, 6:11:09 PM12/19/14
to
In article <slrnm993ma...@xs8.xs4all.nl>,
Ehm, waar staat dat? In de PPP RFC staat dat als de MRU niet
onderhandeld is, hij default naar 1500. Zie RFC1661, paragraaf 6.1.

>Die MRU kun je wel in de telnet interface instellen maar niet in de web
>interface.
>Als dit niet gedaan is dan staat er bij jullie 1500 maar dropt hij alles
>wat >1492 is, en omdat de Juniper dan niks retour stuurt heb je dan grote
>problemen die je alleen weg krijgt door al je interne machines op MTU 1492
>te configureren.

RFC1661 zegt specifiek in 6.1 dat als je een groter packet ontvangt
dan je onderhandeld hebt, je die toch moet processen. Klinkt ook
logisch. Je hebt het packet ontvangen. Waarom dan weggooien.

Klinkt als een Draytek bug?

Mike.

Rob

unread,
Dec 20, 2014, 3:31:04 AM12/20/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>Ik weet niet of dat van jou of van Timo kwam, maar er was al geconstateerd
>>dat ook Draytek producten waar nog geen RFC4638 support in zit bij jullie
>>een MTU van 1500 geven, omdat ze kennelijk de MRU niet opsturen als die
>>niet specifiek ingesteld is en de Juniper dan maar aanneemt dat het 1500
>>is (bug! de RFC zegt dat het dan 1492 is).
>
> Ehm, waar staat dat? In de PPP RFC staat dat als de MRU niet
> onderhandeld is, hij default naar 1500. Zie RFC1661, paragraaf 6.1.

Dat is PPP. Maar we hebben het hier over PPPoE, daar is een aparte
RFC voor (RFC2516) waar in staat dat het 1492 moet zijn.
Achteraf had dat natuurlijk nooit zo hard in die RFC moeten staan, dan
was RFC4638 niet nodig geweest.

>>Die MRU kun je wel in de telnet interface instellen maar niet in de web
>>interface.
>>Als dit niet gedaan is dan staat er bij jullie 1500 maar dropt hij alles
>>wat >1492 is, en omdat de Juniper dan niks retour stuurt heb je dan grote
>>problemen die je alleen weg krijgt door al je interne machines op MTU 1492
>>te configureren.
>
> RFC1661 zegt specifiek in 6.1 dat als je een groter packet ontvangt
> dan je onderhandeld hebt, je die toch moet processen. Klinkt ook
> logisch. Je hebt het packet ontvangen. Waarom dan weggooien.
>
> Klinkt als een Draytek bug?

Ik neem aan dat er ergens een limiet in een chip of driver geprogrammeerd
staat waardoor de te grote ethernet frames gedropped worden als invalid.

Omdat er geen ICMP-achtig protocol voor ethernet is, gebeurt dit uiteraard
silent. En omdat in PPP de "keep alive" separaat gehouden is van het
dataverkeer, heeft de andere kant niks in de gaten. Immers "keep alive"
pakketjes zijn veel kleiner en komen gewoon door.

Ik neem aan dat iedereen met dit probleem zit, anders was dat hele gedoe
met RFC4638 nergens voor nodig geweest en had iedereen gewoon de MTU op
1500 kunnen zetten. Immers "te grote packets moet je gewoon processen".

rene...@gmail.com

unread,
Dec 20, 2014, 4:10:18 AM12/20/14
to
Op vrijdag 19 december 2014 18:49:19 UTC+1 schreef Rob:
> Wellicht negeert hij dat veldje als RFC4638 gesupport wordt.
> Werkt je IPv6 naar allerlei sites zonder dat je zelf hoeft te vogelen
> aan de MTU op je computers?

IPv6 werkt verder uitstekend op diverse sites, zonder de MTU ergens te moeten aanpassen. Dus wat dat betreft is er ook helemaal geen probleem :)

rene...@gmail.com

unread,
Dec 20, 2014, 4:17:10 AM12/20/14
to
Op vrijdag 19 december 2014 21:31:37 UTC+1 schreef Miquel van Smoorenburg:
> Nou, als ik kijk naar je ppp sessie (er even van uit gaande dat je post
> vanaf je thuisverbinding) dan zie ik dit:
>
> ...
>
> Maw, een MTU van 1500. Die Juniper liegt niet :) Ook:
>
> Ik kan je met 1500 bytes packets pingen.
>
> Ik weet niet welke support gezegd heeft dat het niet werkt, maar
> die hebben ongelijk: je MTU is 1500.
>
> Mike.

Dat ben ik inderdaad. Nice! Via de web interface, documentatie en support zie je daar dus niets van terug. Die beweren allemaal dat het niet kan. Bijzonder... wellicht iets wat sinds kort ondersteund wordt in de laatste firmware.

ps: kun je mijn ip nummer nog weg editten? Je bent ergens vergeten om het laatste digit te vervangen door .jij

Rob

unread,
Dec 20, 2014, 6:42:18 AM12/20/14
to
Dan is het dus inderdaad zo dat dit veldje genegeerd wordt.
Ik zit nog te wachten op dezelfde support op mijn Draytek 2860.
Het is wel aangekondigd...

Miquel van Smoorenburg

unread,
Dec 20, 2014, 7:13:47 AM12/20/14
to
In article <slrnm9acu6...@xs8.xs4all.nl>,
Rob <nom...@example.com> wrote:
>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>>Ik weet niet of dat van jou of van Timo kwam, maar er was al geconstateerd
>>>dat ook Draytek producten waar nog geen RFC4638 support in zit bij jullie
>>>een MTU van 1500 geven, omdat ze kennelijk de MRU niet opsturen als die
>>>niet specifiek ingesteld is en de Juniper dan maar aanneemt dat het 1500
>>>is (bug! de RFC zegt dat het dan 1492 is).
>>
>> Ehm, waar staat dat? In de PPP RFC staat dat als de MRU niet
>> onderhandeld is, hij default naar 1500. Zie RFC1661, paragraaf 6.1.
>
>Dat is PPP. Maar we hebben het hier over PPPoE, daar is een aparte
>RFC voor (RFC2516) waar in staat dat het 1492 moet zijn.

Kan het niet vinden. Er staat wel dat het niet boven de 1492 onderhandeld
mag worden, maar er staat nergens dat als je het NIET onderhandeld dat
het dan 1492 is. Kortom, je bent verplicht het te onderhandelen.

>Achteraf had dat natuurlijk nooit zo hard in die RFC moeten staan, dan
>was RFC4638 niet nodig geweest.

Dat komt omdat er tot de dag van vandaag geen IEEE ethernet standaard
is die ethernet packet met een MTU > 1500 toestaat. Jumbo frames-
de hele wereld gebruikt ze - zijn niet standaard.

>>>Die MRU kun je wel in de telnet interface instellen maar niet in de web
>>>interface.
>>>Als dit niet gedaan is dan staat er bij jullie 1500 maar dropt hij alles
>>>wat >1492 is, en omdat de Juniper dan niks retour stuurt heb je dan grote
>>>problemen die je alleen weg krijgt door al je interne machines op MTU 1492
>>>te configureren.
>>
>> RFC1661 zegt specifiek in 6.1 dat als je een groter packet ontvangt
>> dan je onderhandeld hebt, je die toch moet processen. Klinkt ook
>> logisch. Je hebt het packet ontvangen. Waarom dan weggooien.
>>
>> Klinkt als een Draytek bug?
>
>Ik neem aan dat er ergens een limiet in een chip of driver geprogrammeerd
>staat waardoor de te grote ethernet frames gedropped worden als invalid.

Tsja, bug. Wel MRU 1500 onderhandelen (door het niet te onderhandelen)
en dan geen packets van 1500 bytes slikken.

>Omdat er geen ICMP-achtig protocol voor ethernet is, gebeurt dit uiteraard
>silent. En omdat in PPP de "keep alive" separaat gehouden is van het
>dataverkeer, heeft de andere kant niks in de gaten. Immers "keep alive"
>pakketjes zijn veel kleiner en komen gewoon door.
>
>Ik neem aan dat iedereen met dit probleem zit, anders was dat hele gedoe
>met RFC4638 nergens voor nodig geweest en had iedereen gewoon de MTU op
>1500 kunnen zetten. Immers "te grote packets moet je gewoon processen".

Nou, nee, want je weet maar nooit of het hele pad jumbo frames
aankan. Als er een switch in het midden zit die ethernet frames
met een MTU > 1500 niet slikt, heb je een probleem. Vandaar RFC4638;
beide kanten moeten roepen 'ik snap mini-jumbo' als het goed is
hebben ze met z'n tweeen kennis van het hele pad ertussen.

Mike.

Miquel van Smoorenburg

unread,
Dec 20, 2014, 7:14:53 AM12/20/14
to
In article <ae2ebfd4-8793-40f1...@googlegroups.com>,
Helaas niet, niet op alle andere servers op de wereld die ook
de xs4all groepen voeren. Maar zo erg is het niet. Dat IP adres
staat nl gewoon in de headers van elk artikel dat je post, iedereen
kan het sowieso zien. Hoe denk je dat ik eraan kom :)

Mike.

Rob

unread,
Dec 20, 2014, 9:18:16 AM12/20/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>Dat is PPP. Maar we hebben het hier over PPPoE, daar is een aparte
>>RFC voor (RFC2516) waar in staat dat het 1492 moet zijn.
>
> Kan het niet vinden. Er staat wel dat het niet boven de 1492 onderhandeld
> mag worden, maar er staat nergens dat als je het NIET onderhandeld dat
> het dan 1492 is. Kortom, je bent verplicht het te onderhandelen.

Uiteraard is als je niks onderhandelt de MTU 1492 want dat is het startpunt,
net als bij PPP waar het 1500 is.
Die ondehandelingen werken door een afwijkende waarde te sturen waar de
andere kant dan mee akkoord kan gaan.

>>Ik neem aan dat iedereen met dit probleem zit, anders was dat hele gedoe
>>met RFC4638 nergens voor nodig geweest en had iedereen gewoon de MTU op
>>1500 kunnen zetten. Immers "te grote packets moet je gewoon processen".
>
> Nou, nee, want je weet maar nooit of het hele pad jumbo frames
> aankan. Als er een switch in het midden zit die ethernet frames
> met een MTU > 1500 niet slikt, heb je een probleem. Vandaar RFC4638;
> beide kanten moeten roepen 'ik snap mini-jumbo' als het goed is
> hebben ze met z'n tweeen kennis van het hele pad ertussen.

Ja maar dat was niet zo nodig geweest als er niet die keiharde MTU
grens van 1492 in RFC2516 had gestaan. Men kon immers altijd al MTU/MRU
1500 als parameter onderhandelen en eventueel wat echotestjes doen,
daar was geen nieuwe optie voor nodig geweest.

Miquel van Smoorenburg

unread,
Dec 20, 2014, 10:05:23 AM12/20/14
to
In article <slrnm9b198...@xs8.xs4all.nl>,
Rob <nom...@example.com> wrote:
>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>>Dat is PPP. Maar we hebben het hier over PPPoE, daar is een aparte
>>>RFC voor (RFC2516) waar in staat dat het 1492 moet zijn.
>>
>> Kan het niet vinden. Er staat wel dat het niet boven de 1492 onderhandeld
>> mag worden, maar er staat nergens dat als je het NIET onderhandeld dat
>> het dan 1492 is. Kortom, je bent verplicht het te onderhandelen.
>
>Uiteraard is als je niks onderhandelt de MTU 1492 want dat is het startpunt,
>net als bij PPP waar het 1500 is.
>Die ondehandelingen werken door een afwijkende waarde te sturen waar de
>andere kant dan mee akkoord kan gaan.

Dat is niet correct. De RFC zegt dat als je het niet onderhandeld het
1500 is. Iets anders staat er niet in. Je kan wel andere dingen
gaan beredeneren, maar dat is fout: RFCs zijn niet om over te
beredeneren, ze zijn om dingen te implementeren exact zoals
gespecificeerd en niet anders.

Als je daar uitzoneringen op wilt maken moet je dat doen volgens
"the robustness principle" van Jon Postel: "Be conservative in what
you send, be liberal in what you accept". Maar een MRU van 1500
onderhandelen (door het niet te onderhandelen en te "hopen" dat het
1492 is) en vervolgens packets van 1500 bytes niet aannemen is
exact het omgekeerde :)

>>>Ik neem aan dat iedereen met dit probleem zit, anders was dat hele gedoe
>>>met RFC4638 nergens voor nodig geweest en had iedereen gewoon de MTU op
>>>1500 kunnen zetten. Immers "te grote packets moet je gewoon processen".
>>
>> Nou, nee, want je weet maar nooit of het hele pad jumbo frames
>> aankan. Als er een switch in het midden zit die ethernet frames
>> met een MTU > 1500 niet slikt, heb je een probleem. Vandaar RFC4638;
>> beide kanten moeten roepen 'ik snap mini-jumbo' als het goed is
>> hebben ze met z'n tweeen kennis van het hele pad ertussen.
>
>Ja maar dat was niet zo nodig geweest als er niet die keiharde MTU
>grens van 1492 in RFC2516 had gestaan. Men kon immers altijd al MTU/MRU
>1500 als parameter onderhandelen en eventueel wat echotestjes doen,
>daar was geen nieuwe optie voor nodig geweest.

Ja, dat had gekund. Maar dat had je het volledig moeten uitschrijven
en exact moeten specificeren hoe beide kanten het daarover eens
kunnen worden, inclusief tests met full-mtu packets om te kijken
of het wel werkt. Want dat gaat niet "zomaar" werken. Kortom je moet
een RFC schrijven. En dat is ook gedaan, RFC4638.

Nee ik heb inderdaad op dit moment niet veel beters te doen,
en het is rotweer buiten :)

Mike.

rene...@gmail.com

unread,
Dec 20, 2014, 11:51:42 AM12/20/14
to
Op zaterdag 20 december 2014 12:42:18 UTC+1 schreef Rob:
Volgens mij werkt het toch echt niet.
een "ping -4 google.com -l 1472" werkt bijvoorbeeld niet.
maar "ping -4 google.com -l 1464" wel.. dat zou dan 1464+28=1492 zijn.

Rob

unread,
Dec 20, 2014, 11:55:32 AM12/20/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
> Nee ik heb inderdaad op dit moment niet veel beters te doen,
> en het is rotweer buiten :)

Dat dacht ik al. Daarom maar een constructiever onderwerp:

Ik ben aan het tobben met een programma onder Linux wat werkt met
nonblocking sockets. Het is een select-loop die een stel input sockets
leest, en als er ergens data binnenkomt dan verwerkt ie het en stuurt
het door naar een ander socket.

De boel mag niet blocken op output sockets want het is gedeeltelijk
realtime (voip). Er zit echter ook een stuk data tussen waarbij er
plotseling 300K van de ene naar de andere TCP connectie moet.

Het vervelende probleem waar ik tegenaan loop is dat als de outputbuffer
vol is de sendmsg() call wel gedeeltelijk de data schrijft, en dan
terug komt met minder written data dan ik aangeboden heb.

Ik ben op zoek naar een manier om te weten of een sendmsg van een
bepaalde lengte in zijn geheel gaat lukken, indien niet dan kan ik
de input fd tijdelijk uit de select set halen en dan queued de data
op de inputkant waar uiteindelijk het TCP window voor de flow control
zorgt. Als ik het eenmaal gelezen heb en niet kan schrijven dan zit
ik met een blok data opgescheept. Ook nog op een lastige manier want
ik heb de boel netjes met een iov van meerdere elementen aan sendmsg
aangeboden dus als niet alles geschreven wordt dan is tijdelijk bufferen
ook nog niet zo eenvoudig als wanneer alles in 1 buffer staat.
Maar eigenlijk wil ik op die plek helemaal niet bufferen.

Dus ik zoek:
- een manier om de vrije ruimte in de outputbuffer te vragen

of eventueel

- een manier om sendmsg in zijn geheel te laten falen als niet het
hele bericht past
(een sockopt ofzo)

Matthijs Melchior

unread,
Dec 21, 2014, 5:51:58 PM12/21/14
to
Rob,
Zie de manual pages socket(7) en tcp(7), en zoek naar de symbolen SO_SNDBUF en
SIOCOUTQ. Met de eerste kan je de size van de output buffer ophalen en met de
tweede kan de de vulling van die buffer te weten komen.

Groet,
Matthijs.

Miquel van Smoorenburg

unread,
Dec 21, 2014, 7:02:18 PM12/21/14
to
In article <slrnm9bag3...@xs8.xs4all.nl>,
Rob <nom...@example.com> wrote:
>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>> Nee ik heb inderdaad op dit moment niet veel beters te doen,
>> en het is rotweer buiten :)
>
>Dat dacht ik al. Daarom maar een constructiever onderwerp:
>
>Ik ben aan het tobben met een programma onder Linux wat werkt met
>nonblocking sockets. Het is een select-loop die een stel input sockets
>leest, en als er ergens data binnenkomt dan verwerkt ie het en stuurt
>het door naar een ander socket.

Is het eigen programmatuur en kan je iets anders gebruiken dan TCP?
Want in Linux kan je ook het SCTP protocol gebruiken, waarbij
je meerdere channels kan maken binnen 1 connectie, met verschillende
priorities. Als je niet naar een channel kan schrijven, blokkeer
je de input socket, zodra je weer wel kan schrijven schrijf je
de gebufferde data en als dat helemaal gelukt is zet je select
op de input weer aan.

Dit kan je natuurlijk ook doen door de data over 2 TCP sockets te
sturen, 1 voor low-latency VOIP en 1 voor de bulk data. De
juist CoS optie zetten, en een packet scheduler gebruiken die
daar ook naar kijkt.

Mike.

Rob

unread,
Dec 22, 2014, 4:32:12 AM12/22/14
to
Nee het protocol ligt vast, ik ben alleen een her-implementatie aan
het doen van een functie binnen dat protocol.

Het werkt normaal peer-to-peer. Er zijn 2 UDP sockets en 1 TCP socket.
De TCP maakt verbinding met een centrale server en vraagt daar een
lijst van geconnecte gebruikers op (160-350KB) en als hij een connectie
wil maken dan gaat hij met die 2 UDP sockets communiceren met het IP
adres van de tegenpartij wat hij in die lijst vindt
(een voor control en een voor voice).

Maar dat kan de gemiddelde gebruiker niet meer tegenwoordig. Je moet
daarvoor namelijk poorten forwarden in je router. Veel te moeilijk :-)

Dus wat heeft men bedacht: een proxy. De client maakt een TCP verbinding
met die proxy, die heeft die UDP poorten en over jouw TCP verbinding
worden die bovenstaande communicaties gemultiplexed gestuurd. (met
recordjes met een type, lengte en data). Dan kan iedere gebruiker thuis
en mobiel gewoon werken met dit protocol, en bestaande installaties
connecten die heel dit proxy protocol niet kennen. Die praten met de
proxy alsof het een user is.

Nadeel: een proxy kan maar 1 user aan per IP adres.
De proxy is geschreven in Java.
Nu heb ik (daar heb je misschien wel iets over gehoord) sinds kort een
systeem met een groot netblock dus ik dacht, ik ga een flink aantal
proxies op allemaal verschillende IP adressen draaien.
Dus ik dat Java ding 254 keer gestart, nou dat was geen succes want
dit kostte 26MB werkgeheugen per proxy. Maar terug gebracht naar 127 dus.
Nu ik heb een C implementatie gemaakt waarbij alle proxies in 1
proces worden afgewikkeld, dan hoef ik ook niet zoveel sockets te
openen en processen te starten. Dit ene proces kost 1.2MB.
Kortom een winst van een factor van meer dan 2500. (ik haat Java)

Het werkt op zich goed maar het mag natuurlijk niet zo zijn dat als user
1 de lijst opvraagt en 350K in zijn TCP socket krijgt, user 2
die aan het praten is onderbrekingen in de UDP relayering krijgt.
Dus alles moet nonblocking zijn en de select loop moet keurig wat er
binnen komt door sturen naar waar het heen moet.
(client TCP socket -> UDP poorten en tijdelijke uitgaande TCP sessie,
UDP poorten en input op uitgaande TCP sessie -> client TCP socket)

Ik had eerst een setsockopt van SO_SNDBUF en zelfs SO_SNDBUFFORCE
gedaan maar dat blijkt helemaal niet te werken. Geeft wel 0 terug maar
de buffer blijft hetzelfde.
Nu heb ik met sysctl de default send buffer groter gezet en dat helpt wel.
Alleen een definitieve oplossing is het niet want die lijst kan zomaar
weer langer worden.

Rob

unread,
Dec 22, 2014, 4:38:02 AM12/22/14
to
Matthijs Melchior <mmelchior@xs4all> wrote:
> Rob,
> Zie de manual pages socket(7) en tcp(7), en zoek naar de symbolen SO_SNDBUF en
> SIOCOUTQ. Met de eerste kan je de size van de output buffer ophalen en met de
> tweede kan de de vulling van die buffer te weten komen.
>
> Groet,
> Matthijs.

Aha bedankt. Die SO_SNDBUF had ik wel gevonden, alleen is het setten
daarvan kennelijk (tegenwoordig?) een no-op en het ophalen levert alleen
een geschatte waarde omdat deze niet in bytes is maar de size is van
een area waarin de data gestructureerd wordt opgeslagen (SKB's).

Bedankt voor die SIOCOUTQ die was ik nog niet tegen gekomen, maar het
is met die combinatie dus nog steeds niet mogelijk om te bepalen of
een pakket met een bepaalde lengte er nog in zijn geheel in gaat passen.

Ik zit er aan te denken om die SIOCOUTQ dan maar te checken en te
vergelijken met een arbitraire grens waar de queue dan niet boven mag
komen en waarvan ik weet dat die veel minder is dan het maximum.
(64K ofzo)

Zit ik daar boven dan blokkeer ik tijdelijk de input.
Alleen hoe deze dan weer vrij te geven? met een korte timeout dan maar
oid. (0.1 seconde later weer de queue opvragen en kijken of die al weer
veel kleiner is)

Miquel van Smoorenburg

unread,
Dec 22, 2014, 2:04:46 PM12/22/14
to
In article <slrnm9fp8r...@xs8.xs4all.nl>,
Rob <nom...@example.com> wrote:
>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>> Is het eigen programmatuur en kan je iets anders gebruiken dan TCP?
>
>Nee het protocol ligt vast, ik ben alleen een her-implementatie aan
>het doen van een functie binnen dat protocol.
>
>Het werkt normaal peer-to-peer. Er zijn 2 UDP sockets en 1 TCP socket.
>De TCP maakt verbinding met een centrale server en vraagt daar een
>lijst van geconnecte gebruikers op (160-350KB) en als hij een connectie
>wil maken dan gaat hij met die 2 UDP sockets communiceren met het IP
>adres van de tegenpartij wat hij in die lijst vindt
>(een voor control en een voor voice).
>
>Maar dat kan de gemiddelde gebruiker niet meer tegenwoordig. Je moet
>daarvoor namelijk poorten forwarden in je router. Veel te moeilijk :-)
>
>Dus wat heeft men bedacht: een proxy. De client maakt een TCP verbinding
>met die proxy, die heeft die UDP poorten en over jouw TCP verbinding
>worden die bovenstaande communicaties gemultiplexed gestuurd. (met
>recordjes met een type, lengte en data). Dan kan iedere gebruiker thuis
>en mobiel gewoon werken met dit protocol, en bestaande installaties
>connecten die heel dit proxy protocol niet kennen. Die praten met de
>proxy alsof het een user is.
>
>Nadeel: een proxy kan maar 1 user aan per IP adres.

Wat vreemd? Is er geen authenticatie van de client en wordt
hij geauthenticeerd op basis van het IP adres *waarnaar* hij
connect? Dat klinkt nogal ... insecure?

>De proxy is geschreven in Java.
>Nu heb ik (daar heb je misschien wel iets over gehoord) sinds kort een
>systeem met een groot netblock dus ik dacht, ik ga een flink aantal
>proxies op allemaal verschillende IP adressen draaien.
>Dus ik dat Java ding 254 keer gestart, nou dat was geen succes want
>dit kostte 26MB werkgeheugen per proxy. Maar terug gebracht naar 127 dus.

Je kan toch een heel IP block binden aan loopback en de proxy
op * laten luisteren? Met getpeername() en getsockname() kan
je uitvinden wat de source en destination adressen zijn. Wacht,
je hebt zeker de source code van dat java ding niet.

>Nu ik heb een C implementatie gemaakt waarbij alle proxies in 1
>proces worden afgewikkeld, dan hoef ik ook niet zoveel sockets te
>openen en processen te starten. Dit ene proces kost 1.2MB.
>Kortom een winst van een factor van meer dan 2500. (ik haat Java)

Ik heb mezelf laatst Go aangeleerd, dat klinkt als ideaal voor
dit soort dingen. Je kan duizenden en duizenden 'goroutines'
(lightweight threads) starten, dan hoef je niet met 'select',
'poll' of 'epoll' te klooien en eventloops e.d. Gewoon 1 of een
paar goroutines per connectie.

>Het werkt op zich goed maar het mag natuurlijk niet zo zijn dat als user
>1 de lijst opvraagt en 350K in zijn TCP socket krijgt, user 2
>die aan het praten is onderbrekingen in de UDP relayering krijgt.

Dat snap ik niet - elke client heeft toch zijn eigen TCP socket?
Hoe kan het dan zijn dat als de TCP socket van 1 client volloopt
(omdat die client niet snel genoeg leest) dat de werking van
een compleet andere TCP socket in de weg zit? Tenzij je veel te
weinig uitgaande bandbreedte hebt, maar dat kan je beter oplossen.

>Dus alles moet nonblocking zijn en de select loop moet keurig wat er
>binnen komt door sturen naar waar het heen moet.
>(client TCP socket -> UDP poorten en tijdelijke uitgaande TCP sessie,
>UDP poorten en input op uitgaande TCP sessie -> client TCP socket)

Btw, gebruik iets als http://libev.schmorp.de/ ipv zelf
het select wiel uit te vinden.

>Ik had eerst een setsockopt van SO_SNDBUF en zelfs SO_SNDBUFFORCE
>gedaan maar dat blijkt helemaal niet te werken. Geeft wel 0 terug maar
>de buffer blijft hetzelfde.
>Nu heb ik met sysctl de default send buffer groter gezet en dat helpt wel.
>Alleen een definitieve oplossing is het niet want die lijst kan zomaar
>weer langer worden.

Ik snap het probleem nog niet, hoe zitten de clients elkaar
in de weg?

Mike.

robert

unread,
Dec 22, 2014, 2:21:43 PM12/22/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid>:
> In article <slrnm9fp8r...@xs8.xs4all.nl>, Rob
> <nom...@example.com> wrote:
>
>>Nu ik heb een C implementatie gemaakt waarbij alle proxies in 1 proces
>>worden afgewikkeld, dan hoef ik ook niet zoveel sockets te openen en
>>processen te starten. Dit ene proces kost 1.2MB. Kortom een winst van
>>een factor van meer dan 2500. (ik haat Java)
>
> Ik heb mezelf laatst Go aangeleerd, dat klinkt als ideaal voor dit soort
> dingen. Je kan duizenden en duizenden 'goroutines' (lightweight threads)
> starten, dan hoef je niet met 'select', 'poll' of 'epoll' te klooien en
> eventloops e.d. Gewoon 1 of een paar goroutines per connectie.

Ja, ik dacht hetzelfde, maar dan met Node.js streams, daarbij krijg je
extragratis backpressure afhandeling als je trage consumers hebt. Go zal
ook wel iets vergelijkbaars hebben, voor bv Python heb je iets als gevent
dat denk ik ook bruikbaar is.

>>Het werkt op zich goed maar het mag natuurlijk niet zo zijn dat als user
>>1 de lijst opvraagt en 350K in zijn TCP socket krijgt, user 2 die aan het
>>praten is onderbrekingen in de UDP relayering krijgt.
>
> Dat snap ik niet - elke client heeft toch zijn eigen TCP socket? Hoe kan
> het dan zijn dat als de TCP socket van 1 client volloopt (omdat die
> client niet snel genoeg leest) dat de werking van een compleet andere TCP
> socket in de weg zit? Tenzij je veel te weinig uitgaande bandbreedte
> hebt, maar dat kan je beter oplossen.

Voor zover ik begrijp leest de proxy die 350K aan inkomend verkeer eerst
helemaal in en moet het vervolgens moeilijk lopen doen als die 350K niet
direct doorgestuurd kan worden.

En het 'moeilijk doen' kwam bij mij over op een soort van sleep in de hoop
dat daarna die 350K wel opgestuurd kan worden (waar natuurlijk geen enkele
garantie voor is). Tijdens die sleep wordt er verder niks gedaan.

--
robert

Rob

unread,
Dec 22, 2014, 2:34:49 PM12/22/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>Dus wat heeft men bedacht: een proxy. De client maakt een TCP verbinding
>>met die proxy, die heeft die UDP poorten en over jouw TCP verbinding
>>worden die bovenstaande communicaties gemultiplexed gestuurd. (met
>>recordjes met een type, lengte en data). Dan kan iedere gebruiker thuis
>>en mobiel gewoon werken met dit protocol, en bestaande installaties
>>connecten die heel dit proxy protocol niet kennen. Die praten met de
>>proxy alsof het een user is.
>>
>>Nadeel: een proxy kan maar 1 user aan per IP adres.
>
> Wat vreemd? Is er geen authenticatie van de client en wordt
> hij geauthenticeerd op basis van het IP adres *waarnaar* hij
> connect? Dat klinkt nogal ... insecure?

Nee de authenticatie staat hier los van. Je meld je bij die centrale
server, daar log je in met challenge/response en dan krijg je een token
wat die andere client weer bij de server valideert.

Maar dat staat helemaal los van de proxy. De proxy is er alleen maar
om gebrek aan peer-to-peer connectiviteit te omzeilen.

> Je kan toch een heel IP block binden aan loopback en de proxy
> op * laten luisteren? Met getpeername() en getsockname() kan
> je uitvinden wat de source en destination adressen zijn. Wacht,
> je hebt zeker de source code van dat java ding niet.

Jawel dat doe ik ook zo. Maar de Java software is maar voor 1 adres.
Dan heb je het probleem waar ik nu tegenaan loop niet: hij copieert
gewoon van socket naar socket en merkt wel wanneer het blockt.

> Ik heb mezelf laatst Go aangeleerd, dat klinkt als ideaal voor
> dit soort dingen. Je kan duizenden en duizenden 'goroutines'
> (lightweight threads) starten, dan hoef je niet met 'select',
> 'poll' of 'epoll' te klooien en eventloops e.d. Gewoon 1 of een
> paar goroutines per connectie.

Ja zolang het maar niet blockt. Multithreaded is dit gemakkelijker op
te lossen uiteraard.

>>Het werkt op zich goed maar het mag natuurlijk niet zo zijn dat als user
>>1 de lijst opvraagt en 350K in zijn TCP socket krijgt, user 2
>>die aan het praten is onderbrekingen in de UDP relayering krijgt.
>
> Dat snap ik niet - elke client heeft toch zijn eigen TCP socket?
> Hoe kan het dan zijn dat als de TCP socket van 1 client volloopt
> (omdat die client niet snel genoeg leest) dat de werking van
> een compleet andere TCP socket in de weg zit? Tenzij je veel te
> weinig uitgaande bandbreedte hebt, maar dat kan je beter oplossen.

Omdat als je een sendmsg op een blocking socket doet en dan komt de
hele select loop stil te staan en wordt er dus voor andere users ook
niet meer gerelayeerd. Dat is het nadeel van single threaded.

> Btw, gebruik iets als http://libev.schmorp.de/ ipv zelf
> het select wiel uit te vinden.

Het voordeel van het zelf doen is dat het veel efficienter is.
"handige bouwblokken die resources slurpen" dat had ik al (Java).

> Ik snap het probleem nog niet, hoe zitten de clients elkaar
> in de weg?

Ik hoop dat dit nu duidelijk is.
Inmiddels heb ik een "oplossing" met die SIOCOUTQ geprogrammeerd.
Weliswaar is dat polling, maar aangezien dit probleem niet regelmatig
optreedt is dat niet zo erg. In de routine die TCP data doorcopieert
check ik na een sendmsg de SIOCOUTQ en is dat groter dan een grenswaarde
dan haal ik de select bit voor de input weg en zet een timer event van
200ms (dat betekent dat de volgende select binnen 200ms terug komt)
en dan check ik weer die SIOCOUTQ en is die onder een andere grens dan
gaat het select bit weer aan. Dit zou moeten werken.

robert

unread,
Dec 22, 2014, 2:45:54 PM12/22/14
to
Rob <nom...@example.com>:
> Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>
>> Dat snap ik niet - elke client heeft toch zijn eigen TCP socket? Hoe kan
>> het dan zijn dat als de TCP socket van 1 client volloopt (omdat die
>> client niet snel genoeg leest) dat de werking van een compleet andere
>> TCP socket in de weg zit? Tenzij je veel te weinig uitgaande bandbreedte
>> hebt, maar dat kan je beter oplossen.
>
> Omdat als je een sendmsg op een blocking socket doet...

Je werkte toch met non-blocking sockets?

>> Btw, gebruik iets als http://libev.schmorp.de/ ipv zelf het select wiel
>> uit te vinden.
>
> Het voordeel van het zelf doen is dat het veel efficienter is.

Met NIH kun je ook doorslaan.

> "handige bouwblokken die resources slurpen" dat had ik al (Java).

Dat had weinig met Java an-sich te maken (daar kun je ook prima hele snelle
netwerkproxies mee bouwen die duizenden verbindingen kunnen afhandelen),
maar met die specifieke Java-app, die maar één verbinding kon proxyen.

> Inmiddels heb ik een "oplossing" met die SIOCOUTQ geprogrammeerd.
> Weliswaar is dat polling, maar aangezien dit probleem niet regelmatig
> optreedt is dat niet zo erg. In de routine die TCP data doorcopieert
> check ik na een sendmsg de SIOCOUTQ en is dat groter dan een grenswaarde
> dan haal ik de select bit voor de input weg en zet een timer event van
> 200ms (dat betekent dat de volgende select binnen 200ms terug komt) en
> dan check ik weer die SIOCOUTQ en is die onder een andere grens dan gaat
> het select bit weer aan. Dit zou moeten werken.

Is dat nou zoveel efficiënter als libev?

--
robert

Rob

unread,
Dec 22, 2014, 2:55:59 PM12/22/14
to
robert <US3N37+{x.g}@gmail.com> wrote:
> Rob <nom...@example.com>:
>> Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>>
>>> Dat snap ik niet - elke client heeft toch zijn eigen TCP socket? Hoe kan
>>> het dan zijn dat als de TCP socket van 1 client volloopt (omdat die
>>> client niet snel genoeg leest) dat de werking van een compleet andere
>>> TCP socket in de weg zit? Tenzij je veel te weinig uitgaande bandbreedte
>>> hebt, maar dat kan je beter oplossen.
>>
>> Omdat als je een sendmsg op een blocking socket doet...
>
> Je werkte toch met non-blocking sockets?

Ja maar dan krijg je dus de problemen die ik moest oplossen.
sendmsg die ineens zegt "ik kon niet alles schrijven" zonder dat je daar
van te voren een indicatie van kunt krijgen.

>>> Btw, gebruik iets als http://libev.schmorp.de/ ipv zelf het select wiel
>>> uit te vinden.
>>
>> Het voordeel van het zelf doen is dat het veel efficienter is.
>
> Met NIH kun je ook doorslaan.
>
>> "handige bouwblokken die resources slurpen" dat had ik al (Java).
>
> Dat had weinig met Java an-sich te maken (daar kun je ook prima hele snelle
> netwerkproxies mee bouwen die duizenden verbindingen kunnen afhandelen),
> maar met die specifieke Java-app, die maar één verbinding kon proxyen.

Nou niet alleen hoor.
Die ene losse proxy kostte al 26MB en gebruikte aardig wat CPU als hij
actief was. Plus dat het dynamisch alloceren van geheugen er ook nog
voor zorgt dat dit proces langzaam groeit.
Mijn C proxy kost maar 1.2MB voor 127 proxies en gebruikt nauwelijks CPU.
(30 seconden per dag ofzo)

>> Inmiddels heb ik een "oplossing" met die SIOCOUTQ geprogrammeerd.
>> Weliswaar is dat polling, maar aangezien dit probleem niet regelmatig
>> optreedt is dat niet zo erg. In de routine die TCP data doorcopieert
>> check ik na een sendmsg de SIOCOUTQ en is dat groter dan een grenswaarde
>> dan haal ik de select bit voor de input weg en zet een timer event van
>> 200ms (dat betekent dat de volgende select binnen 200ms terug komt) en
>> dan check ik weer die SIOCOUTQ en is die onder een andere grens dan gaat
>> het select bit weer aan. Dit zou moeten werken.
>
> Is dat nou zoveel efficiënter als libev?

Ja, want die conditie treedt maar eens in de paar uur op. Meestal is dat
hele probleem er niet. Maar als je goede software wilt maken dan wil je
ook problemen oplossen die maar zo nu en dan optreden.

robert

unread,
Dec 23, 2014, 1:56:32 AM12/23/14
to
Rob <nom...@example.com>:
> robert <US3N37+{x.g}@gmail.com> wrote:
>
>> Dat had weinig met Java an-sich te maken (daar kun je ook prima hele
>> snelle netwerkproxies mee bouwen die duizenden verbindingen kunnen
>> afhandelen), maar met die specifieke Java-app, die maar één verbinding
>> kon proxyen.
>
> Nou niet alleen hoor. Die ene losse proxy kostte al 26MB en gebruikte
> aardig wat CPU als hij actief was. Plus dat het dynamisch alloceren van
> geheugen er ook nog voor zorgt dat dit proces langzaam groeit.

Nogmaals, dat heeft weinig met Java an-sich te maken, het klinkt gewoon als
een slecht geschreven programma. Alhoewel een JVM wel meer geheugen
gebruikt dan een simpel C progje, maar zou die 26MB een groot probleem zijn
geweest als het wél fatsoenlijk had gewerkt (met meerdere verbindingen)?

> Mijn C proxy kost maar 1.2MB voor 127 proxies en gebruikt nauwelijks CPU.
> (30 seconden per dag ofzo)

Ik kan me voorstellen dat dat belangrijk is als je het op zeer beperkte
hardware draait, maar een gemiddelde server doet toch niet moeilijk over
enkele tientallen MB's?

>> Is dat nou zoveel efficiënter als libev?
>
> Ja, want die conditie treedt maar eens in de paar uur op. Meestal is dat
> hele probleem er niet. Maar als je goede software wilt maken dan wil je
> ook problemen oplossen die maar zo nu en dan optreden.

Ik zie niet in wat dat allemaal met libev te maken heeft. De onderliggende
mechanismen die libev gebruikt zijn inherent efficiënter dan select(). In
jouw geval zal het overigens weinig tot niks uitmaken.

--
robert

Rob

unread,
Dec 23, 2014, 3:44:01 AM12/23/14
to
robert <US3N37+{x.g}@gmail.com> wrote:
> Rob <nom...@example.com>:
>> robert <US3N37+{x.g}@gmail.com> wrote:
>>
>>> Dat had weinig met Java an-sich te maken (daar kun je ook prima hele
>>> snelle netwerkproxies mee bouwen die duizenden verbindingen kunnen
>>> afhandelen), maar met die specifieke Java-app, die maar één verbinding
>>> kon proxyen.
>>
>> Nou niet alleen hoor. Die ene losse proxy kostte al 26MB en gebruikte
>> aardig wat CPU als hij actief was. Plus dat het dynamisch alloceren van
>> geheugen er ook nog voor zorgt dat dit proces langzaam groeit.
>
> Nogmaals, dat heeft weinig met Java an-sich te maken, het klinkt gewoon als
> een slecht geschreven programma. Alhoewel een JVM wel meer geheugen
> gebruikt dan een simpel C progje, maar zou die 26MB een groot probleem zijn
> geweest als het wél fatsoenlijk had gewerkt (met meerdere verbindingen)?

Ik hou op met de discussie over Java. Mijn ervaring met Java is dat er
altijd hordes mensen zijn die zeggen dat het allemaal goed kan werken, maar
als ik een Java programma heb dan werkt het altijd slecht.
Dan is het altijd "een slecht geschreven programma". Goed geschreven
Java programma's zijn er kennelijk niet.

>> Mijn C proxy kost maar 1.2MB voor 127 proxies en gebruikt nauwelijks CPU.
>> (30 seconden per dag ofzo)
>
> Ik kan me voorstellen dat dat belangrijk is als je het op zeer beperkte
> hardware draait, maar een gemiddelde server doet toch niet moeilijk over
> enkele tientallen MB's?

Nee als in die 26MB meerdere proxies zouden draaien dan zou het geen
probleem geweest zijn inderdaad. De server heeft 4 GB en 4 2GHz cores
en dat zou voldoende moeten zijn, maar hij doet ook veel andere dingen.

>>> Is dat nou zoveel efficiënter als libev?
>>
>> Ja, want die conditie treedt maar eens in de paar uur op. Meestal is dat
>> hele probleem er niet. Maar als je goede software wilt maken dan wil je
>> ook problemen oplossen die maar zo nu en dan optreden.
>
> Ik zie niet in wat dat allemaal met libev te maken heeft. De onderliggende
> mechanismen die libev gebruikt zijn inherent efficiënter dan select(). In
> jouw geval zal het overigens weinig tot niks uitmaken.

libev is toch een user-level ding? Wat doet die dan voor geheime dingen
die efficienter zijn dan select? Daar kan ik me weinig bij voorstellen.

robert

unread,
Dec 23, 2014, 3:49:02 AM12/23/14
to
Rob <nom...@example.com>:
> libev is toch een user-level ding? Wat doet die dan voor geheime dingen
> die efficienter zijn dan select? Daar kan ik me weinig bij voorstellen.

En toch beweer je met enige stelligheid dat jouw oplossing efficiënter is?

--
robert

Rob

unread,
Dec 23, 2014, 4:30:51 AM12/23/14
to
robert <US3N37+{x.g}@gmail.com> wrote:
Ja, want ik zit rechtstreeks op de system interface.

robert

unread,
Dec 23, 2014, 6:51:29 AM12/23/14
to
Rob <nom...@example.com>:
select() is aan alle kanten verouderd: O(N) complexiteit, beperkte
hoeveelheid fd's die je ermee in de gaten kunt houden, je moet elke keer de
hele lijst aan fd's doorlopen om te zien welke er lees-/schrijfbaar zijn,
de semantiek in geval van bv gesloten sockets is vreemd (de socket wordt
als 'leesbaar' gemarkeerd), en select() icm threads is oppassen geblazen.

libev(/libevent/libuv) maakt gebruik van de 'modernere' (die al minstens 10
jaar bestaan) vervangers van select().

--
robert

Miquel van Smoorenburg

unread,
Dec 23, 2014, 7:07:51 AM12/23/14
to
In article <slrnm9iaqh...@xs8.xs4all.nl>,
Rob <nom...@example.com> wrote:
>libev is toch een user-level ding? Wat doet die dan voor geheime dingen
>die efficienter zijn dan select? Daar kan ik me weinig bij voorstellen.

Die gebruikt mechanismes zoals epoll() of kevent() die veeeel efficienter
zijn dan select(). Er zit ook een timer-systeem ingebouwd.
Efficiente datastructuren ook om dingen als timers en events op
filedescriptors op te zoeken, zodat je als je veel filedescriptors
of timers tegelijk gebruikt je efficientie meer op O(1) lijkt dan O(N).
Geen linked-lists maar R/B trees ofzo.

Wat je meestal doet is dat je alle data betreffende een verbinding
(in/uit filedescriptors, buffers, counters, state) in een struct zet.
Die alloceer je met malloc(). Vervolgens registreer je de filedescriptors
met het event systeem waarbij je ook een functie-pointer en een pointer
naar die struct meegeeft. Als er dan 'iets' gebeurt (filedesc wordt
leesbaar of schrijfbaar) dan wordt die functie aangeroepen, met
als argument o.a. die pointer naar je struct. Een callback systeem dus.
Je kan natuurlijk per filedescriptor verschillende callback functies
gebruiken als dat handig is.

Op die manier is het veel makkelijker om per-connectie of per
set filedescriptors iets te doen. Non-blocking is dan geen probleem.
Als er op de TCP socket veel data binnenkomt buffer je dat
eerst in z'n geheel. Mogelijk moet je dat in meerdere keren lezen,
dus je moet een counter bijhouden hoe vol je buffer inmiddels is.
Als die data binnen is dan schrijf je die naar de client-tcp-socket.
Als dat niet in 1x past, zet je voor alle filedescriptors het
'read' event uit, en alleen voor de uitgaande socket het 'write'
event aan. Dan krijg je daarna alleen een callback als je kan
schrijven. Net zolang tot je hele buffer geschreven is, dan draai
je die events weer om.

Overigens doe je het maken van uitgaande connecties op dezelfde
manier, je roept connect() aan, maar die zal -EINPROGRESS
teruggeven. Je krijgt een callback zodra de connectie er is.
Dat is iets waar je anders ook tegenaan kan lopen, dat kan ook
een flinke delay geven af en toe.

Als je detecteert dat de verbinding gesloten is, zeg je tegen
libev dat je geen interesse meer hebt in callbacks voor je
filedescriptors, close() je alle filedescriptors, free() je de
struct met data, en klaar.

Mike.

Casper H.S. Dik

unread,
Dec 23, 2014, 7:11:10 AM12/23/14
to
US3N37+{x.g}@gmail.com (robert) writes:

>select() is aan alle kanten verouderd: O(N) complexiteit, beperkte
>hoeveelheid fd's die je ermee in de gaten kunt houden, je moet elke keer de
>hele lijst aan fd's doorlopen om te zien welke er lees-/schrijfbaar zijn,
>de semantiek in geval van bv gesloten sockets is vreemd (de socket wordt
>als 'leesbaar' gemarkeerd), en select() icm threads is oppassen geblazen.

We hadden nog geluk dat de argumenten pointers waren zodat de definitie
vrij makkelijk van "pointer naar een integer" naar "pointer naar een
array van integers".

poll() was een betere definitie (een lijstje van fds met een
lijst events) maar ook dat schaalt niet lekker als je 1000en fds
in de gaten wil houden.

Maar ik denk dat je niet begrijp wat leesbaar betekent in de
context van select(): het betekent alleen maar dat een
"blocking read" meteen antwoord zal geven. End-of-file wordt
nu eenmaal aangegeven al een read() die 0 bytes oplevert.

>libev(/libevent/libuv) maakt gebruik van de 'modernere' (die al minstens 10
>jaar bestaan) vervangers van select().

Afgezien van de niet schalen, is een van de problemen met select() is
dat als je select een niet valide descriptor geeft, dan krijg je
alleen maar error retrn ("EBADF") en dan moet je het zelf verder
uitzoeken.

Casper

Miquel van Smoorenburg

unread,
Dec 23, 2014, 7:16:53 AM12/23/14
to
In article <slrnm9gsio...@xs8.xs4all.nl>,
Rob <nom...@example.com> wrote:
>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>> Wat vreemd? Is er geen authenticatie van de client en wordt
>> hij geauthenticeerd op basis van het IP adres *waarnaar* hij
>> connect? Dat klinkt nogal ... insecure?
>
>Nee de authenticatie staat hier los van. Je meld je bij die centrale
>server, daar log je in met challenge/response en dan krijg je een token
>wat die andere client weer bij de server valideert.
>
>Maar dat staat helemaal los van de proxy. De proxy is er alleen maar
>om gebrek aan peer-to-peer connectiviteit te omzeilen.

Maar ik snap nog steeds niet waarom elke client naar een uniek
IP adres moet connecten. Wat voegt dat toe?

>> Ik heb mezelf laatst Go aangeleerd, dat klinkt als ideaal voor
>> dit soort dingen. Je kan duizenden en duizenden 'goroutines'
>> (lightweight threads) starten, dan hoef je niet met 'select',
>> 'poll' of 'epoll' te klooien en eventloops e.d. Gewoon 1 of een
>> paar goroutines per connectie.
>
>Ja zolang het maar niet blockt. Multithreaded is dit gemakkelijker op
>te lossen uiteraard.

Zie mijn andere posting waarin ik uitleg hoe je dit met een
eventing systeem kan oplossen.

Overigens om hoeveel connecties gaat het? Waarom niet multithreaded?
Onder Linux zijn duizenden threads geen probleem (mits op 64 bits).
Op moderne BSDs ook, lijkt me.

Het is jammer dat het je 1 of 2 weken kost om je thuis te
voelen in Go. Dat is veel tijd. Maar dan schrijf je de proxy
waar je het over hebt binnen een dag, en schaalt het als een malle.
Ik zou iets doen met een goroutine per socket, of beter,
1 per richting van een socket, en de boel laten communiceren
via channels (voornamelijk de writes).

Mike.

Rob

unread,
Dec 23, 2014, 7:33:06 AM12/23/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
> In article <slrnm9iaqh...@xs8.xs4all.nl>,
> Rob <nom...@example.com> wrote:
>>libev is toch een user-level ding? Wat doet die dan voor geheime dingen
>>die efficienter zijn dan select? Daar kan ik me weinig bij voorstellen.
>
> Die gebruikt mechanismes zoals epoll() of kevent() die veeeel efficienter
> zijn dan select().

Aha die epoll die kende ik niet, alleen (p)select en (p)poll, en die
hebben allemaal hetzelfde nadeel. Wat (p)poll betreft is dat natuurlijk
een gemiste kans, als die alleen een array terug zou geven met de
werkelijk actieve fd's dan was er helemaal geen issue.

Maar dit is zowizo niet zo'n issue omdat 99% van het verkeer op de
eerste 3 fd's is en dan valt er weinig te zoeken.

> Wat je meestal doet is dat je alle data betreffende een verbinding
> (in/uit filedescriptors, buffers, counters, state) in een struct zet.
> Die alloceer je met malloc(). Vervolgens registreer je de filedescriptors
> met het event systeem waarbij je ook een functie-pointer en een pointer
> naar die struct meegeeft. Als er dan 'iets' gebeurt (filedesc wordt
> leesbaar of schrijfbaar) dan wordt die functie aangeroepen, met
> als argument o.a. die pointer naar je struct. Een callback systeem dus.
> Je kan natuurlijk per filedescriptor verschillende callback functies
> gebruiken als dat handig is.

Dat is min of meer wat ik ook doe in mijn programma alleen dan door
middel van een registratiesysteem voor fd's die aan select gevoerd
worden en na de return van de select worden de bitjes gescand en de
geregistreerde functies aangeroepen. Een standaard stukje code wat
ik al had liggen.
Dit kan wellicht snel worden omgebouwd naar gebruik van epoll.

> Op die manier is het veel makkelijker om per-connectie of per
> set filedescriptors iets te doen. Non-blocking is dan geen probleem.

Ik denk dat het daarvoor niet veel uitmaakt...

> Als er op de TCP socket veel data binnenkomt buffer je dat
> eerst in z'n geheel. Mogelijk moet je dat in meerdere keren lezen,
> dus je moet een counter bijhouden hoe vol je buffer inmiddels is.

Ja maar dat wil je natuurlijk niet, het ding moet zo weinig mogelijk
bufferen. Dat doet mijn implementatie ook niet, alles wat met recvmsg
ontvangen is gaat er meteen daarna met sendmsg weer uit.

> Als die data binnen is dan schrijf je die naar de client-tcp-socket.
> Als dat niet in 1x past, zet je voor alle filedescriptors het
> 'read' event uit, en alleen voor de uitgaande socket het 'write'
> event aan. Dan krijg je daarna alleen een callback als je kan
> schrijven. Net zolang tot je hele buffer geschreven is, dan draai
> je die events weer om.

Nadeel is dan dat je gedurende dat hele lange blok niks meer in kunt
voegen. Het bekende "upload beinvloedt download" probleem. Dat
heeft mijn oplossing niet.

> Overigens doe je het maken van uitgaande connecties op dezelfde
> manier, je roept connect() aan, maar die zal -EINPROGRESS
> teruggeven. Je krijgt een callback zodra de connectie er is.
> Dat is iets waar je anders ook tegenaan kan lopen, dat kan ook
> een flinke delay geven af en toe.

Ja dat doe ik al.

> Als je detecteert dat de verbinding gesloten is, zeg je tegen
> libev dat je geen interesse meer hebt in callbacks voor je
> filedescriptors, close() je alle filedescriptors, free() je de
> struct met data, en klaar.

Dat doe ik ook al. Maar een eigenschap van mijn code is dat er
niks gemalloced en gefreed wordt gedurende normaal gebruik, allen
tijdens de initialisatie (om de datastructuren per proxy te alloceren).
Er is dus geen creep in het memorygebruik. Iets wat in C vaak wel
meevalt maar waar de Java versie wel last van had. Dat zijn geen
lekken maar dat komt door fragmentatie van de memory pool en in
het geval van Java door het "garbage collector" model.

Rob

unread,
Dec 23, 2014, 7:35:35 AM12/23/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
> In article <slrnm9gsio...@xs8.xs4all.nl>,
> Rob <nom...@example.com> wrote:
>>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>> Wat vreemd? Is er geen authenticatie van de client en wordt
>>> hij geauthenticeerd op basis van het IP adres *waarnaar* hij
>>> connect? Dat klinkt nogal ... insecure?
>>
>>Nee de authenticatie staat hier los van. Je meld je bij die centrale
>>server, daar log je in met challenge/response en dan krijg je een token
>>wat die andere client weer bij de server valideert.
>>
>>Maar dat staat helemaal los van de proxy. De proxy is er alleen maar
>>om gebrek aan peer-to-peer connectiviteit te omzeilen.
>
> Maar ik snap nog steeds niet waarom elke client naar een uniek
> IP adres moet connecten. Wat voegt dat toe?

Dat is gewoon het protocol wat dom is. Een client == een IP adres.
Je staat in de "available clients" tabel met je IP adres. Zeg maar
je telefoonnummer.

>>> Ik heb mezelf laatst Go aangeleerd, dat klinkt als ideaal voor
>>> dit soort dingen. Je kan duizenden en duizenden 'goroutines'
>>> (lightweight threads) starten, dan hoef je niet met 'select',
>>> 'poll' of 'epoll' te klooien en eventloops e.d. Gewoon 1 of een
>>> paar goroutines per connectie.
>>
>>Ja zolang het maar niet blockt. Multithreaded is dit gemakkelijker op
>>te lossen uiteraard.
>
> Zie mijn andere posting waarin ik uitleg hoe je dit met een
> eventing systeem kan oplossen.

Ja dat is een goed verhaal maar laat duidelijk zijn: het ene probleem
wat ik hier aankaartte wordt hier niet door opgelost. Het is een
andere manier om (wellicht sneller) te coderen wat ik nu heb samengeraapt
uit vorige programma's, kennis en ervaring, maar het flow control
probleem is exact hetzelfde.

Rob

unread,
Dec 23, 2014, 7:38:44 AM12/23/14
to
Casper H.S Dik <Caspe...@OrSPaMcle.COM> wrote:
> poll() was een betere definitie (een lijstje van fds met een
> lijst events) maar ook dat schaalt niet lekker als je 1000en fds
> in de gaten wil houden.

Het domme van poll is dat het net als select de input en output parameter
deelt. Men had natuurlijk een apart array voor de output events moeten
maken met een teruggegeven lengte, zodat je alleen die events hoeft te
scannen die zijn opgetreden.

> Afgezien van de niet schalen, is een van de problemen met select() is
> dat als je select een niet valide descriptor geeft, dan krijg je
> alleen maar error retrn ("EBADF") en dan moet je het zelf verder
> uitzoeken.

Ja dat had ik al opgelost, als er EBADF terug komt dan wordt de lijst
van fd's doorzocht en worden ze allemaal getest of ze nog geldig zijn
en de foute eruit gegooid. Dat gebeurt overigens in dit programma
niet, dat is een overblijfsel uit eerder gebruik van de code. Met
een fatsoenlijk laag om die fd boekhouding heen heb je hier geen last
van, want een fd geeft eerst EOF voor hij gesloten wordt.

robert

unread,
Dec 23, 2014, 7:44:38 AM12/23/14
to
Casper H.S Dik <Caspe...@OrSPaMcle.COM>:
> Maar ik denk dat je niet begrijp wat leesbaar betekent in de context van
> select(): het betekent alleen maar dat een "blocking read" meteen
> antwoord zal geven. End-of-file wordt nu eenmaal aangegeven al een
> read() die 0 bytes oplevert.

Dat select() zo werkt weet ik, maar met (e)poll (en ook met kqueue) heb je
meteen al duidelijkheid over dat het gaat om een verbinding die gesloten is
en hoef je niet nog een read() uit te voeren om daar achter te komen.
Daarin is select() gewoon beperkter, bedoelde ik te zeggen :)

--
robert

Miquel van Smoorenburg

unread,
Dec 23, 2014, 7:45:28 AM12/23/14
to
In article <slrnm9io81...@xs8.xs4all.nl>,
Rob <nom...@example.com> wrote:
>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>> In article <slrnm9iaqh...@xs8.xs4all.nl>,
>> Rob <nom...@example.com> wrote:
>>>libev is toch een user-level ding? Wat doet die dan voor geheime dingen
>>>die efficienter zijn dan select? Daar kan ik me weinig bij voorstellen.
>>
>> Die gebruikt mechanismes zoals epoll() of kevent() die veeeel efficienter
>> zijn dan select().
>
>Aha die epoll die kende ik niet, alleen (p)select en (p)poll, en die
>hebben allemaal hetzelfde nadeel. Wat (p)poll betreft is dat natuurlijk
>een gemiste kans, als die alleen een array terug zou geven met de
>werkelijk actieve fd's dan was er helemaal geen issue.

Dat is toch ook zo .. poll() geeft je alleen een array terug
met de werkelijk actieve fd's. Nadeel is alleen dat als je
veel filedescriptors hebt, poll() elke keer de hele struct poll
array de kernel in moet kopieeren en de kernel de hele setup
elke keer overnieuw moet doen.

>> Als er op de TCP socket veel data binnenkomt buffer je dat
>> eerst in z'n geheel. Mogelijk moet je dat in meerdere keren lezen,
>> dus je moet een counter bijhouden hoe vol je buffer inmiddels is.
>
>Ja maar dat wil je natuurlijk niet, het ding moet zo weinig mogelijk
>bufferen. Dat doet mijn implementatie ook niet, alles wat met recvmsg
>ontvangen is gaat er meteen daarna met sendmsg weer uit.

Waarom boeit dat, dat bufferen? Of het nou in een user-space
buffer of een kernel-socket-buffer hangt.

>> Als die data binnen is dan schrijf je die naar de client-tcp-socket.
>> Als dat niet in 1x past, zet je voor alle filedescriptors het
>> 'read' event uit, en alleen voor de uitgaande socket het 'write'
>> event aan. Dan krijg je daarna alleen een callback als je kan
>> schrijven. Net zolang tot je hele buffer geschreven is, dan draai
>> je die events weer om.
>
>Nadeel is dan dat je gedurende dat hele lange blok niks meer in kunt
>voegen. Het bekende "upload beinvloedt download" probleem. Dat
>heeft mijn oplossing niet.

Tuurlijk is dat geen probleem. Als je maar event-based denkt :)

Maar goed, je moet het zelf weten. De hele wereld gebruikt
non-blocking filedescriptors en buffers. Dat is om een reden :)

Mike.

Miquel van Smoorenburg

unread,
Dec 23, 2014, 7:48:42 AM12/23/14
to
In article <slrnm9iobv...@xs8.xs4all.nl>,
Rob <nom...@example.com> wrote:
>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>> In article <slrnm9gsio...@xs8.xs4all.nl>,
>> Rob <nom...@example.com> wrote:
>>>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>>> Wat vreemd? Is er geen authenticatie van de client en wordt
>>>> hij geauthenticeerd op basis van het IP adres *waarnaar* hij
>>>> connect? Dat klinkt nogal ... insecure?
>>>
>>>Nee de authenticatie staat hier los van. Je meld je bij die centrale
>>>server, daar log je in met challenge/response en dan krijg je een token
>>>wat die andere client weer bij de server valideert.
>>>
>>>Maar dat staat helemaal los van de proxy. De proxy is er alleen maar
>>>om gebrek aan peer-to-peer connectiviteit te omzeilen.
>>
>> Maar ik snap nog steeds niet waarom elke client naar een uniek
>> IP adres moet connecten. Wat voegt dat toe?
>
>Dat is gewoon het protocol wat dom is. Een client == een IP adres.
>Je staat in de "available clients" tabel met je IP adres. Zeg maar
>je telefoonnummer.

Wacht. Ik snap het - het unieke IP adres is niet iets waar de
client naar connect, maar je gebruikt het voor de uitgaande
connectie vanaf de proxy naar de 'echte' server, want die heeft
een uniek IP per client nodig, ook als het de proxy is. Dat was
me voorheen niet duidelijk. Zeg, kan je niet gewoon IPv6 gebruiken? :)
(een andere oplossing is een IP-IP tunnel en 10.0.0.0/8 adressen
daarover routeren)

Mike.

Miquel van Smoorenburg

unread,
Dec 23, 2014, 7:57:00 AM12/23/14
to
In article <549963d6$0$2931$e4fe...@news2.news.xs4all.nl>,
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>In article <slrnm9io81...@xs8.xs4all.nl>,
>Rob <nom...@example.com> wrote:
>>Aha die epoll die kende ik niet, alleen (p)select en (p)poll, en die
>>hebben allemaal hetzelfde nadeel. Wat (p)poll betreft is dat natuurlijk
>>een gemiste kans, als die alleen een array terug zou geven met de
>>werkelijk actieve fd's dan was er helemaal geen issue.
>
>Dat is toch ook zo .. poll() geeft je alleen een array terug
>met de werkelijk actieve fd's. Nadeel is alleen dat als je
>veel filedescriptors hebt, poll() elke keer de hele struct poll
>array de kernel in moet kopieeren en de kernel de hele setup
>elke keer overnieuw moet doen.

Herstel, het is blijkbaar veel te lang geleden dat ik poll()
heb gebruikt. Idd, er zijn geen aparte struct poll arrays
voor in en uit.

Mike.

Casper H.S. Dik

unread,
Dec 23, 2014, 8:02:29 AM12/23/14
to
Rob <nom...@example.com> writes:

>Aha die epoll die kende ik niet, alleen (p)select en (p)poll, en die
>hebben allemaal hetzelfde nadeel. Wat (p)poll betreft is dat natuurlijk
>een gemiste kans, als die alleen een array terug zou geven met de
>werkelijk actieve fd's dan was er helemaal geen issue.

De bedoeling is natuurlijk dat je dezelfde lijst continu kan geven en
dat je dus geen aparte administratie bij moet houden; dat laatste moet
bij select() wel.

poll() is natuurlijk ook uitgevonden toen een process maar weinig fds
kon hebben. In Solaris is er functie geschreven die werkt zoals
jij het graag bij poll had gehad: het krijgen van een lijst van
file descriptors die gepolled zijn (/dev/poll). Natuurlijk later
ook een event gebaseerd mechanisme gemaakt.

>> Als die data binnen is dan schrijf je die naar de client-tcp-socket.
>> Als dat niet in 1x past, zet je voor alle filedescriptors het
>> 'read' event uit, en alleen voor de uitgaande socket het 'write'
>> event aan. Dan krijg je daarna alleen een callback als je kan
>> schrijven. Net zolang tot je hele buffer geschreven is, dan draai
>> je die events weer om.

>Nadeel is dan dat je gedurende dat hele lange blok niks meer in kunt
>voegen. Het bekende "upload beinvloedt download" probleem. Dat
>heeft mijn oplossing niet.

Tenzij je dat op een andere thread doet.

>Dat doe ik ook al. Maar een eigenschap van mijn code is dat er
>niks gemalloced en gefreed wordt gedurende normaal gebruik, allen
>tijdens de initialisatie (om de datastructuren per proxy te alloceren).
>Er is dus geen creep in het memorygebruik. Iets wat in C vaak wel
>meevalt maar waar de Java versie wel last van had. Dat zijn geen
>lekken maar dat komt door fragmentatie van de memory pool en in
>het geval van Java door het "garbage collector" model.

Het maakt bij Java veel uit precies welke data structuren je
gebruikt; vaak kan je het herschrijven zodat er minder gealloceerd
wordt. En natuurlijk niet een JVM per connectie; gewoon veel
threads in de JVM.

Casper

Casper H.S. Dik

unread,
Dec 23, 2014, 8:17:03 AM12/23/14
to
Rob <nom...@example.com> writes:

>Het domme van poll is dat het net als select de input en output parameter
>deelt. Men had natuurlijk een apart array voor de output events moeten
>maken met een teruggegeven lengte, zodat je alleen die events hoeft te
>scannen die zijn opgetreden.

Dat zou het performance probleem maar heel gedeeltelijk mee helpen; want
je moet bij de volgende poll weer alle file descriptors meegeven en
bij iedere aanroep van poll() en select() moet je eerst zeggen dat je
wacht voor een bepaald event en aan het einde zal je zeggen dat je
daar niet meer opwacht. Dat is nou wat zo duur is; niet het copieren
van een paar extra bytes over de fds waar niets aan de hand is.

In Solaris 7 is een pseudo device driver toegevoerd: "/dev/poll" en
daar schrijf je alle poll events waar je op wacht en dan vraag je later
bij welke fds er een event gebeurd is. Maar je blijft dan nog steeds
wachten voor de events op de andere fds. Later is er algemener
mechanisme gekomen in Solaris (event ports); vergelijkbaar met
BSD's kqueue en libevent/epoll op Linux.

>Ja dat had ik al opgelost, als er EBADF terug komt dan wordt de lijst
>van fd's doorzocht en worden ze allemaal getest of ze nog geldig zijn
>en de foute eruit gegooid. Dat gebeurt overigens in dit programma
>niet, dat is een overblijfsel uit eerder gebruik van de code. Met
>een fatsoenlijk laag om die fd boekhouding heen heb je hier geen last
>van, want een fd geeft eerst EOF voor hij gesloten wordt.

Ja, dat is met poll net even makkelijker.

Casper

Rob

unread,
Dec 23, 2014, 8:27:09 AM12/23/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
> Waarom boeit dat, dat bufferen? Of het nou in een user-space
> buffer of een kernel-socket-buffer hangt.

Het maakt wel verschil of je eerst alle data verzamelt en dat in een
keer in de TCP queue mikt, of dat je blokje voor blokje overzet en
de UDP datagrammen daar tussen laat.

> Maar goed, je moet het zelf weten. De hele wereld gebruikt
> non-blocking filedescriptors en buffers. Dat is om een reden :)

Ik gebruik ook non-blocking sockets.
Maar waar ik tegenaan loop is dat de laatste write meestal gedeeltelijk
lukt, ipv dat je kunt kiezen of een bepaalde sendmsg in zijn geheel
wel of niet lukt. Heb je net een mooie scatter/gather interface (iov)
en dan word je met zo iets opgezadeld.

Plus dat ik graag een early-warning mechanisme zou hebben zodat ik de
source kan afknijpen voordat de destination tegen de limiet aan loopt.

Rob

unread,
Dec 23, 2014, 8:28:41 AM12/23/14
to
Casper H.S Dik <Caspe...@OrSPaMcle.COM> wrote:
> Rob <nom...@example.com> writes:
>
>>Het domme van poll is dat het net als select de input en output parameter
>>deelt. Men had natuurlijk een apart array voor de output events moeten
>>maken met een teruggegeven lengte, zodat je alleen die events hoeft te
>>scannen die zijn opgetreden.
>
> Dat zou het performance probleem maar heel gedeeltelijk mee helpen; want
> je moet bij de volgende poll weer alle file descriptors meegeven en
> bij iedere aanroep van poll() en select() moet je eerst zeggen dat je
> wacht voor een bepaald event en aan het einde zal je zeggen dat je
> daar niet meer opwacht. Dat is nou wat zo duur is; niet het copieren
> van een paar extra bytes over de fds waar niets aan de hand is.

Het copieren blijft hetzelfde maar die array staat gewoon klaar, en
het zou schelen in het doorzoeken van de array als de call terugkomt.

Casper H.S. Dik

unread,
Dec 23, 2014, 8:31:11 AM12/23/14
to
"Miquel van Smoorenburg" <mik...@xs4all.nederland.invalid> writes:

>Herstel, het is blijkbaar veel te lang geleden dat ik poll()
>heb gebruikt. Idd, er zijn geen aparte struct poll arrays
>voor in en uit.

Maar er is een event en revent. Je hoeft dus geen aparte
boekhouding te doen.

De kosten van poll() zijn niet het kopieren in en uit de kernel
maar dat je veel werk dubbel doet: als je poll() returned, wil
je eigenlijk nog steeds wachten op de andere fds maar dat kan
niet dus je moet dat wachten ongedaan maken en je moet
het opnieuw en opnieuw .... doen.

Dus poll() is altijd O(N) voor het aantal actieve file descriptors,
terwijl libevent O(1) is.


Casper

Casper H.S. Dik

unread,
Dec 23, 2014, 8:32:52 AM12/23/14
to
Rob <nom...@example.com> writes:

>Het copieren blijft hetzelfde maar die array staat gewoon klaar, en
>het zou schelen in het doorzoeken van de array als de call terugkomt.

Ja maar ik zou wedden dat het niet of nauwlijks meetbaar is.

Casper

Rob

unread,
Dec 23, 2014, 8:34:12 AM12/23/14
to
Het is geen client-server protocol maar peer-to-peer. Je kunt die client
die je connect natuurlijk de server noemen. Je kunt zelf achter een proxy
hangen en/of je peer kan achter een proxy hangen maar dat weer je helemaal
niet, hij staat met zijn proxy adres in de lijst en daar connect je heen.

Eigenlijk is die proxy een soort VPN inderdaad. Men had het ook kunnen
oplossen met openvpn ofzo. Dat doen we zelf ook voor andere doeleinden.
Maar deze oplossing zit nou eenmaal in die client.

Het is allemaal oud en hardwired IPv4. Maar "iedereen heeft het"
en het zou wel beter zijn om een nieuw protocol te bedenken maar
dan moet je ook weer al die clients gaan schrijven, wat een hele
klus is en geen leuk werk.
(Windows, Mac, Linux, Ios, Android, Windows Phone)

Rob

unread,
Dec 23, 2014, 8:39:27 AM12/23/14
to
Casper H.S Dik <Caspe...@OrSPaMcle.COM> wrote:
Denk ik ook ja, maar ik ben er dan ook niet over begonnen dat dit een
probleem zou zijn.

Rob

unread,
Dec 23, 2014, 8:45:56 AM12/23/14
to
Casper H.S Dik <Caspe...@OrSPaMcle.COM> wrote:
> "Miquel van Smoorenburg" <mik...@xs4all.nederland.invalid> writes:
>
>>Herstel, het is blijkbaar veel te lang geleden dat ik poll()
>>heb gebruikt. Idd, er zijn geen aparte struct poll arrays
>>voor in en uit.
>
> Maar er is een event en revent. Je hoeft dus geen aparte
> boekhouding te doen.
>
> De kosten van poll() zijn niet het kopieren in en uit de kernel
> maar dat je veel werk dubbel doet: als je poll() returned, wil
> je eigenlijk nog steeds wachten op de andere fds maar dat kan
> niet dus je moet dat wachten ongedaan maken en je moet
> het opnieuw en opnieuw .... doen.

Ik moet zeggen dat het programma met select (eigenlijk hetzelfde als poll)
heel goed werkt, en vele andere programma's die ik van binnen ken ook.

Het enige wat je in een beetje complexer programma zelf goed moet regelen
is het beheer van die fd sets.

Als je het event-based maakt introduceer je weet het probleem van de
concurrency en locking, en dat probleem heb ik nu helemaal niet omdat
er maar 1 thread is.

Miquel van Smoorenburg

unread,
Dec 23, 2014, 9:46:23 AM12/23/14
to
In article <slrnm9irdc...@xs8.xs4all.nl>,
Rob <nom...@example.com> wrote:
>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>> Waarom boeit dat, dat bufferen? Of het nou in een user-space
>> buffer of een kernel-socket-buffer hangt.
>
>Het maakt wel verschil of je eerst alle data verzamelt en dat in een
>keer in de TCP queue mikt, of dat je blokje voor blokje overzet en
>de UDP datagrammen daar tussen laat.

Oh, je kan die grote datablokken in stukjes versturen ipv in 1x?
Dan kan je natuurlijk op het moment dat de tcp socket schrijfbaar
is eerst je UDP packets eroverheen sturen, als je die nog
gebufferd hebt, en daarna een stukje van dat grote datablok,
toch? om en om.

>Ik gebruik ook non-blocking sockets.
>Maar waar ik tegenaan loop is dat de laatste write meestal gedeeltelijk
>lukt, ipv dat je kunt kiezen of een bepaalde sendmsg in zijn geheel
>wel of niet lukt. Heb je net een mooie scatter/gather interface (iov)
>en dan word je met zo iets opgezadeld.

Ja, ik heb ook gezocht of er een socketoptie is in Linux
die zegt 'alles of niets', maar dat kon ik niet vinden. Ik
denk dat het niet bestaat. Nogmaals jammer dat SCTP niet
aan wil slaan, het lost al deze problemen op en meer.

>Plus dat ik graag een early-warning mechanisme zou hebben zodat ik de
>source kan afknijpen voordat de destination tegen de limiet aan loopt.

Maar dat kan toch, het is net hoe je erover denkt. Of de data
nou in een socket buffer zit of in een userspace buffer.. Je
kan beter de output socket buffer zo klein mogelijk houden en zoveel
mogelijk in userspace bufferen, dan kan je beter bepalen
wat voorrang moet krijgen. Altijd eerst UDP en pas TCP als
er ruimte is (of als er een timer is afgegaan, op een gegeven
moment moet je die data toch doorgeven)

In ieder geval, veel succes. Ik hoop dat je eruit komt.

Mike.

Rob

unread,
Dec 23, 2014, 10:00:48 AM12/23/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
> In article <slrnm9irdc...@xs8.xs4all.nl>,
> Rob <nom...@example.com> wrote:
>>Miquel van Smoorenburg <mik...@xs4all.nederland.invalid> wrote:
>>> Waarom boeit dat, dat bufferen? Of het nou in een user-space
>>> buffer of een kernel-socket-buffer hangt.
>>
>>Het maakt wel verschil of je eerst alle data verzamelt en dat in een
>>keer in de TCP queue mikt, of dat je blokje voor blokje overzet en
>>de UDP datagrammen daar tussen laat.
>
> Oh, je kan die grote datablokken in stukjes versturen ipv in 1x?
> Dan kan je natuurlijk op het moment dat de tcp socket schrijfbaar
> is eerst je UDP packets eroverheen sturen, als je die nog
> gebufferd hebt, en daarna een stukje van dat grote datablok,
> toch? om en om.

Ja wat ik na die tip mbt TIOCOUTQ doe is een bepaalde hi-water mark
aanhouden die nog beneden de maximale queue zit, komt ie daar boven
dan wordt het TCP->TCP pad stil gezet door het input bit uit de
select set the halen, maar UDP->TCP gaat gewoon door tot er een
error terug komt uit de sendmsg.

>>Plus dat ik graag een early-warning mechanisme zou hebben zodat ik de
>>source kan afknijpen voordat de destination tegen de limiet aan loopt.
>
> Maar dat kan toch, het is net hoe je erover denkt. Of de data
> nou in een socket buffer zit of in een userspace buffer.. Je
> kan beter de output socket buffer zo klein mogelijk houden en zoveel
> mogelijk in userspace bufferen, dan kan je beter bepalen
> wat voorrang moet krijgen. Altijd eerst UDP en pas TCP als
> er ruimte is (of als er een timer is afgegaan, op een gegeven
> moment moet je die data toch doorgeven)

Ja dat zou leuk zijn maar helaas is er dus geen atomic sendmsg call
en ik kan natuurlijk niet een record gedeeltelijk schrijven en dan
een UDP record er tussendoor. Dus moet ik dan dat gedeeltelijke
record uit de iov peuren en bewaren voor eerst mogelijke sendmsg.
Dat is me allemaal te lastig. Sinds die throttle er in zit is dit
probleem in feite weg, en als de buffer nu nog vol loopt gooi ik
de user er gewoon uit (te slechte verbinding kennelijk).

> In ieder geval, veel succes. Ik hoop dat je eruit komt.

Ja het draait nu goed. Die ene ioctl heeft het probleem in feite
opgelost, ik had liever gehad dat ie de available space kon
teruggeven want nu moet ik garanderen dat de systeem default buffer
groter is dan de harde hi-water mark maar dat is nu zo en voorlopig
draait dit ding alleen op onze eigen server.

robert

unread,
Dec 23, 2014, 10:30:25 AM12/23/14
to
Miquel van Smoorenburg <mik...@xs4all.nederland.invalid>:
> Ja, ik heb ook gezocht of er een socketoptie is in Linux die zegt 'alles
> of niets', maar dat kon ik niet vinden.

In OS X (en ongetwijfeld *BSD) heb je (in ieder geval volgens de manpage)
de hele handige SO_SNDLOWAT sockopt: "A select(2) operation testing the
ability to write to a socket will return true only if the low-water mark
amount could be processed".

--
robert

Rob

unread,
Dec 23, 2014, 10:56:21 AM12/23/14
to
robert <US3N37+{x.g}@gmail.com> wrote:
Kijk daar heb je wat aan!
Alleen, er bestaat wel een optie met die naam in Linux maar die doet
heel wat anders. Waar ik niks aan heb.

Richard Bos

unread,
Dec 23, 2014, 4:48:04 PM12/23/14
to
Rob <nom...@example.com> wrote:

> Ik hou op met de discussie over Java. Mijn ervaring met Java is dat er
> altijd hordes mensen zijn die zeggen dat het allemaal goed kan werken, maar
> als ik een Java programma heb dan werkt het altijd slecht.
> Dan is het altijd "een slecht geschreven programma". Goed geschreven
> Java programma's zijn er kennelijk niet.

Jawel hoor, die zijn er wel. Maar die draaien niet op webservers.

Richard

Rob

unread,
Dec 24, 2014, 5:07:35 AM12/24/14
to
Nou het programma waar ik het nu over heb draait ook niet op een webserver,
en niet in een browser. Het draait (draaide) in een java vm op een
algemene server.
Het had last van zowel de bekende over-use van resources als van de
neiging om alsmaar te expanderen. Ik heb het nog gestart met de
optie -Xmx2M die me beloofde een cap op de heap sectie te zetten maar
dat maakte helaas weinig uit.

En wat doet dat programma dan fout? het gebruikt de bekende techniek
om per message die het aanpakt een new object te creeren, waarin de
message wordt ingelezen en meteen weer weg te sturen waarna het object
dus weer buiten gebruik is. Tuurlijk, moet je nooit zo doen maar het
is wel algemeen gebruikelijk in dit soort talen. Waar die mensen geen
rekening mee houden is dat al die gealloceerde objecten "garbage" worden
en dat de Java VM eerst een tijdje extra memory bij het OS gaat vragen
en pas als er een grens wordt overschreden (waarvan ik had aangenomen
dat ik die met die -Xmx2M zou afdwingen) dan gaat ie "garbage collecten"
maar dat maakt alleen de pool beschikbaar voor nieuw gebruik, er wordt
niks terug gegeven aan het OS.

In C wordt wat je free()'d meteen weer beschikbaar voor allocatie,
gewoon veel beter. En ik heb bovendien de C versie nu zo geschreven
dat hij helemaal geen alloc/free doet per getransporteerd bericht, maar
eenmalig bij startup een buffer aanmaakt voor ieder bericht wat er
verder doorheen gaat. Dat lost het definitief op.

Het kan zijn dat Java slechte programmeurs aantrekt hoor. Dat komt
misschien doordat mensen er in C niet meer uitkomen omdat ze geen
fundamentele kennis hebben, en dan in Java ontdekken dat hun programma's
niet meer in segmentation violations lopen, hiep hoi.
Maar in C heb je ook geen last van dit soort problemen als je weet waar
je mee bezig bent.

robert

unread,
Dec 24, 2014, 5:24:21 AM12/24/14
to
Rob <nom...@example.com>:
> Maar in C heb je ook geen last van dit soort problemen als je weet waar
> je mee bezig bent.

En in Java geldt precies hetzelfde: als je weet waar je mee bezig bent heb
je geen last van dat soort problemen.

Ik ben geen Java-fan, maar ik heb wel ervaring met Java-based apps die zich
heel netjes gedragen en maandenlang (zo niet jarenlang) draaien zonder
problemen te geven (op het moment heb ik bv Elasticsearch op m'n Mac
draaien, dat draait sinds de laatste reboot, ruim een maand geleden, en
ondanks zeer regelmatig gebruik blijft het geheugen- en CPU-gebruik vrij
constant).

--
robert

Rob

unread,
Dec 24, 2014, 5:47:53 AM12/24/14
to
robert <US3N37+{x.g}@gmail.com> wrote:
> Rob <nom...@example.com>:
>> Maar in C heb je ook geen last van dit soort problemen als je weet waar
>> je mee bezig bent.
>
> En in Java geldt precies hetzelfde: als je weet waar je mee bezig bent heb
> je geen last van dat soort problemen.

Even voor de duidelijkheid: "dit soort problemen" daarmee bedoel ik
crashes door segmentation violations en andere issues door overkladderd
geheugen. Daar zul je in Java geen last van hebben nee.

> Ik ben geen Java-fan, maar ik heb wel ervaring met Java-based apps die zich
> heel netjes gedragen en maandenlang (zo niet jarenlang) draaien zonder
> problemen te geven (op het moment heb ik bv Elasticsearch op m'n Mac
> draaien, dat draait sinds de laatste reboot, ruim een maand geleden, en
> ondanks zeer regelmatig gebruik blijft het geheugen- en CPU-gebruik vrij
> constant).

Wel constant vrij hoog, neem ik aan.

robert

unread,
Dec 24, 2014, 6:55:26 AM12/24/14
to
Rob <nom...@example.com>:
> robert <US3N37+{x.g}@gmail.com> wrote:
>> Rob <nom...@example.com>:
>>> Maar in C heb je ook geen last van dit soort problemen als je weet waar
>>> je mee bezig bent.
>>
>> En in Java geldt precies hetzelfde: als je weet waar je mee bezig bent
>> heb je geen last van dat soort problemen.
>
> Even voor de duidelijkheid: "dit soort problemen" daarmee bedoel ik
> crashes door segmentation violations en andere issues door overkladderd
> geheugen. Daar zul je in Java geen last van hebben nee.

En ik bedoelde oneindig groeiend geheugen.

>> Ik ben geen Java-fan, maar ik heb wel ervaring met Java-based apps die
>> zich heel netjes gedragen en maandenlang (zo niet jarenlang) draaien
>> zonder problemen te geven (op het moment heb ik bv Elasticsearch op m'n
>> Mac draaien, dat draait sinds de laatste reboot, ruim een maand geleden,
>> en ondanks zeer regelmatig gebruik blijft het geheugen- en CPU-gebruik
>> vrij constant).
>
> Wel constant vrij hoog, neem ik aan.

200MB, ongeveer de grootte van de database. Maar op de 16GB die er in m'n
Mac zit is dat verwaarloosbaar, en als er écht geheugen nodig is wordt de
zaak wel uitgeswapped.

--
robert

Richard Bos

unread,
Dec 24, 2014, 7:00:52 AM12/24/14
to
Rob <nom...@example.com> wrote:

> Richard Bos <ral...@xs4all.nl> wrote:
> > Rob <nom...@example.com> wrote:
> >
> >> Ik hou op met de discussie over Java. Mijn ervaring met Java is dat er
> >> altijd hordes mensen zijn die zeggen dat het allemaal goed kan werken, maar
> >> als ik een Java programma heb dan werkt het altijd slecht.
> >> Dan is het altijd "een slecht geschreven programma". Goed geschreven
> >> Java programma's zijn er kennelijk niet.
> >
> > Jawel hoor, die zijn er wel. Maar die draaien niet op webservers.
>
> Nou het programma waar ik het nu over heb draait ook niet op een webserver,
> en niet in een browser. Het draait (draaide) in een java vm op een
> algemene server.

Nou ja, same difference. Java werkt wel (min of meer) voor kleine,
individuele programmaatjes. Voor meer gebruikers is het niet geschikt.

> In C wordt wat je free()'d meteen weer beschikbaar voor allocatie,
> gewoon veel beter.

Nou... in principe wel, maar dat moet allemaal ook maar passen. Ook in C
loop je vroeger of later tegen alloc arena fragmentatie aan. Daar is
gewoon niets aan te doen, zonder bijzondere (en potentieel tijdrovende)
kunstgrepen toe te passen. Maar als je weet wat je doet is het
natuurlijk wel een stuk efficienter dan Java.

> Het kan zijn dat Java slechte programmeurs aantrekt hoor. Dat komt
> misschien doordat mensen er in C niet meer uitkomen omdat ze geen
> fundamentele kennis hebben, en dan in Java ontdekken dat hun programma's
> niet meer in segmentation violations lopen, hiep hoi.

Dat, en Java is gewoon modieuzer dan C, en trekt dus zoiezo al het soort
mensen aan dat eerder geschikt is om script kiddie of middle manager te
worden. Zie ook: Micro$oft C-flat.

Richard

robert

unread,
Dec 24, 2014, 7:46:14 AM12/24/14
to
Richard Bos <ral...@xs4all.nl>:
> ...en Java is gewoon modieuzer dan C...

Alles is modieuzer dan C.

> ...en trekt dus zoiezo al het soort mensen aan dat eerder geschikt is om
> script kiddie of middle manager te worden.

Ik hoop maar dat jij geen Android telefoon bij je draagt, die zou spontaan
rebooten van al die FUD.

--
robert

Rob

unread,
Dec 24, 2014, 8:00:40 AM12/24/14
to
robert <US3N37+{x.g}@gmail.com> wrote:
> Rob <nom...@example.com>:
>> robert <US3N37+{x.g}@gmail.com> wrote:
>>> Rob <nom...@example.com>:
>>>> Maar in C heb je ook geen last van dit soort problemen als je weet waar
>>>> je mee bezig bent.
>>>
>>> En in Java geldt precies hetzelfde: als je weet waar je mee bezig bent
>>> heb je geen last van dat soort problemen.
>>
>> Even voor de duidelijkheid: "dit soort problemen" daarmee bedoel ik
>> crashes door segmentation violations en andere issues door overkladderd
>> geheugen. Daar zul je in Java geen last van hebben nee.
>
> En ik bedoelde oneindig groeiend geheugen.

Tja het groeide niet oneindig maar het werd gewoon op den duur meer,
en het was al een probleem omdat ik 254 instances van hetzelfde programma
wilde draaien. Dan wordt het heel belangrijk dat die allemaal stabiel
zijn kwa geheugengebruik.

>>> Ik ben geen Java-fan, maar ik heb wel ervaring met Java-based apps die
>>> zich heel netjes gedragen en maandenlang (zo niet jarenlang) draaien
>>> zonder problemen te geven (op het moment heb ik bv Elasticsearch op m'n
>>> Mac draaien, dat draait sinds de laatste reboot, ruim een maand geleden,
>>> en ondanks zeer regelmatig gebruik blijft het geheugen- en CPU-gebruik
>>> vrij constant).
>>
>> Wel constant vrij hoog, neem ik aan.
>
> 200MB, ongeveer de grootte van de database. Maar op de 16GB die er in m'n
> Mac zit is dat verwaarloosbaar, en als er écht geheugen nodig is wordt de
> zaak wel uitgeswapped.

De server waar ik op wil draaien heeft 4GB geheugen en dat is bij normaal
gebruik prima, maar als je 26MB per proces gaat gebruiken dan ga je er
wel sneller doorheen.

Rob

unread,
Dec 24, 2014, 8:04:33 AM12/24/14
to
Richard Bos <ral...@xs4all.nl> wrote:
>> In C wordt wat je free()'d meteen weer beschikbaar voor allocatie,
>> gewoon veel beter.
>
> Nou... in principe wel, maar dat moet allemaal ook maar passen. Ook in C
> loop je vroeger of later tegen alloc arena fragmentatie aan. Daar is
> gewoon niets aan te doen, zonder bijzondere (en potentieel tijdrovende)
> kunstgrepen toe te passen. Maar als je weet wat je doet is het
> natuurlijk wel een stuk efficienter dan Java.

Ja en omdat ik dat weet (ik onderhield al een TCP/IP stack in de tijd
dat je maar 200K memory vrij had voor malloc) heb ik in dit specifieke
geval, waarin het gaat om 1 op 1 berichten doorsturen die een in de
protocol spec gedefineerde maximale lengte hebben geconcludeerd dat je
beter bij startup 1 keer een buffer per instance kunt alloceren die
gebruikt wordt voor alle berichten, dan een hip dynamisch buffer object
wat steeds op maat gealloceerd wordt en daardoor ook nog een extra memcopy
nodig maakt (omdat recvmsg je pas achteraf vertelt hoe groot het volgende
bericht is).

robert

unread,
Dec 24, 2014, 8:31:14 AM12/24/14
to
Eén process per peer-to-peer verbinding is natuurlijk sowieso een waste of
resources, ongeacht in welke taal de zaak geschreven is.

--
robert

Rob

unread,
Dec 24, 2014, 9:00:56 AM12/24/14
to
Tja het heeft ook een IP adres per verbinding nodig dus ik kan me wel
voorstellen dat het zo geschreven is. Dan heb je ook geen last van het
issue waar ik tegenaan liep mbt de flow control.
(nouja je hebt er wel last van maar je merkt het minder)

Als dat Java nou een beetje goed in elkaar zat dan was er niet zoveel
nonshared memory tussen al die instances, maar goed en Java vind je nooit
bij elkaar in de buurt. (ik niet, in ieder geval)
0 new messages