[Megoldva] Ruby socket: magas cpu load

Sziasztok!

ruby --version
ruby 1.8.7 (2010-08-16 patchlevel 302) [x86_64-linux] (Gentoo)

Lenne egy olyan (lehet triviális, nem látom fától az erdőt) problémám, hogy a következő kódsor miért terheli 100%-ban cpu -t:


require 'socket'

server = TCPServer.open(9010)
loop {
Thread.start(server.accept_nonblock) do |client|
client.puts 'Haliho!'
client.close
end
}

Amikor megszakítom a folyamatot, akkor a 'Thread.start(server.accept_nonblock) do |client|' sornál várakozik.
A TCP connectek szépen mennek, nincs baj. Próbáltam már szimplán server.accept -el, szálasítás nélkül, loop {} nélkül is, sikertelenül. Tanácstalan vagyok.

Köszönöm!

Megoldás:
A bug nem a Ruby-ban van, hanem az én programomban bújkált.
Ha fenti kódot ha ki akarod próbálni akkor server.accept_nonblock _helyett_ server.accept -et használj, azzal futni fog.

Hozzászólások

nonblock
ezert. igy nem is fog menni. csak magas load-dal. a nonblock rossz, ertem? ;)

server.accept
igy kell csinalni. igen, ez meg nem egyszeru". multiplexeles is kell ha nem akarsz szalasitani, valahogy, amit a nyelv tamogat. nem ismerem a ruby-t, de a c-beli select()-nek megfelelo" helyen keresgelj. illetve csinalhatsz me'g a sigio/sigpoll-nak megfelelo "kivetelezo" variaciot is, az is egy kellemes lehetoseg, csak az (szvsz) megnyugvenyelosebb.

egyebkent nekem igy siman _nonblock nelkul mukodokepesnek tunik a dolog. persze a multitaszk-reszet (tobb kliens) ennel jobban teszteld:


require 'socket'

server = TCPServer.open(9010)
loop {
Thread.start(server.accept) do |client|
client.puts 'Haliho!'
sleep(3)
client.puts 'qqriq'
client.close
end
}

nalam (deb, lenny, default ruby: ruby 1.8.7 (2008-08-11 patchlevel 72) [x86_64-linux]) ez a fenti tokeletesen megy, 2 kliensre is es nem terheli a procit egyatalan.

a.

hm, mondjuk az eredeti valtozatot is kiprobaltam amit irtal, es az nem megy:


$ ruby x.ruby 
x.ruby:5:in `accept_nonblock': Resource temporarily unavailable - accept(2) (Errno::EAGAIN)
        from x.ruby:5
        from x.ruby:4:in `loop'
        from x.ruby:4

(egyebkent a c-vel eleg szoros a kapcsolat, innen latszik, mert egy nonblock socket az accept()-re ugyanugy errno==eagain-nal ter vissza /azaz hibaval!/, mint c-ben, szoval ezek a ruby-fuggvenyek gyk 1:1 megfeleltetesek lehetnek a libc-s valtozatra /gyk berkeley socket api-ra/, es nem a nyelv szerves resze)

Megadtad a kulcsot a megoldáshoz :)

Az eredeti programrészt átmásoltam egy üres állományba, majd onnan futtatva, nekem se terhelt semmit és a fenti nonblock-os hibát dobta. Az eredeti helyén azért "működött" mert ha a 9010-es port hibát dob, akkor megpróbálja 9011-esen a szervert, de míg a 9010-es valamiért nonblock -os, a 9011 már nem az (én se értem miért, szerintem sima figyelmetlenség), mindezt a teszt kliensben is csendben lekezelve én pedig nem is figyeltem a portokra, csak arra hogy tekeri a cpu-t és hogy megy.

Aztán elkezdtem a programomat sorról - sorra átnézni és kiderült hogy az egész herce-hurca egy másik állományban bújkáló, új szálon induló programrész miatt volt, ahol sikerült egy végtelen ciklust alkotni, így hiába kommentelgettem ki közel mindent, nem ott volt a hiba, ahol vártam.

Ha nem írod, hogy neked működik szerintem beláthatatlan ideig szívtam volna a dologgal. Jó kis lecke volt.

Szóval, köszönöm! :)