{"id":3216,"date":"2014-04-14T13:11:27","date_gmt":"2014-04-14T12:11:27","guid":{"rendered":"http:\/\/t-machine.org\/?p=3216"},"modified":"2014-04-14T13:12:13","modified_gmt":"2014-04-14T12:12:13","slug":"debugging-odd-problems-when-writing-game-servers","status":"publish","type":"post","link":"http:\/\/new.t-machine.org\/index.php\/2014\/04\/14\/debugging-odd-problems-when-writing-game-servers\/","title":{"rendered":"Debugging odd problems when writing game servers"},"content":{"rendered":"<p><a href=\"https:\/\/twitter.com\/puppygames\">Cas (@PuppyGames)<\/a> (of PuppyGames fame &#8211; <a href=\"http:\/\/puppygames.net\/titan-attacks\/\">Titan Attacks<\/a>, <a href=\"http:\/\/puppygames.net\/revenge-of-the-titans\/\">Revenge of the Titans<\/a>, etc) is working on an awesome new MMO RTS &#8230; thing.<\/p>\n<p>He had a weird networking problem, and was looking for suggestions on possible causes. I used to do a lot of MMO dev, so we ran through the &#8220;typical&#8221; problems. This isn&#8217;t exhaustive, but as a quick-n-dirty checklist, I figured it could help some other indie gamedevs doing multiplayer\/network code.<\/p>\n<h2>Scenario<\/h2>\n<ol>\n<li>Java, Windows 7\n<li>DataInputStream.readFully() from a socket&#8230; a local socket at that&#8230; taking 4.5 seconds to read the first bytes\n<li>and I&#8217;ve already read a few bits and bobs out of it\n<\/ol>\n<h2>Initial thoughts<\/h2>\n<p>First thought: in networking, everything has a realm of durations. The speed of light means that a network connection from New York to London takes a few milliseconds (unavoidably) &#8211; everything is measured in ms, unless you&#8217;re on a local machine, in which case: the OS internally works in microseconds (almost too small to measure). Since Cas&#8217;s problem is measured in SECONDS &#8211; but is on localhost &#8211; it&#8217;s probably something external to the OS, external to the networking itself.<\/p>\n<p>Gut feel would be something like Nagle&#8217;s algorithm, although I&#8217;m sure everyone&#8217;s already configured that appropriately ;).<\/p>\n<p>That, or a routing table that&#8217;s changing dynamically &#8211; e.g. first packet is triggering a &#8220;let me start the dialup connection for you&#8221;, causing everything to pause (note that &#8220;4 seconds&#8221; is in the realm of time it takes for modems to connect; it&#8217;s outside the realm of ethernet delays, as already noted)<\/p>\n<p>My general advice for &#8220;bizarre server-networking bugs&#8221;: start doing the things you know are &#8220;wrong&#8221; from a performance view, and prove that each makes it worse. If one does not, that de facto that one is somehow not configured as intended.<\/p>\n<h2>Common causes \/ things to check<\/h2>\n<p>1. Contention: waht&#8217;s the CPU + C libraries doing in background? If system has any significant (but small) load, you could be contended on I\/O, CPU mgiht not be interrupting to shunt data from hardware up to software (kernel), up to software (OS user), up to JVM<\/p>\n<p>Classic example: MySQL DB running on a system can block I\/O even with small CPU load<\/p>\n<p>2. file-level locking in OS FS. Check using <a href=\"http:\/\/en.wikipedia.org\/wiki\/Lsof\">lsof<\/a> which files your JVM is accessing, and what other processes in the machine may have same files open.<\/p>\n<p>(NB: there&#8217;s a bunch of tools like &#8220;lsof&#8221; which let you see which files are in use by which processes in a unix\/linux system. As a network programmer, you should learn them all &#8211; they can save a lot of time in development. As a network programmer, you need to be a competent SysAdmin!)<\/p>\n<p>Classic problem: something unexpected has an outstanding read (or a pre-emptive write lock) which is causing silliness. I remember several times having a text editor open, or etc, that was inadvertently slowing access to local files (doh).<\/p>\n<p>3. can you snoop the traffic? (i.e. its socket, not pipe)<\/p>\n<p>Classic problem: some unrelated service is bombarding the loopback with crap. eg. Windows networking (samba on linux) going nuts<\/p>\n<p>Try running Wireshark, filtered to show only 127. and see what&#8217;s going through at same time<\/p>\n<p>Also: this is a good way to check where the delay is happening. Is it at point of send, or point of receive? &#8230; both?<\/p>\n<p>There&#8217;s &#8220;net traffic&#8221; and there&#8217;s &#8220;net traffic&#8221;. Wireshark often shows traffic that OS normally filters out from monitoring apps&#8230;<\/p>\n<p>4. Check your routing table? AND: Check it&#8217;s not changing before \/ aftter the attempted read?<\/p>\n<p>5. Try enabling <a href=\"http:\/\/en.wikipedia.org\/wiki\/Nagle%27s_algorithm\">Nagle<\/a>, see if it has any effect?<\/p>\n<p>My point is: use this as a check: it ought to make things worse. If not &#8230; perhaps the disabling wasn&#8217;t working?<\/p>\n<p>6. Have you done ANY traffic shaping (or firewalling) on this machine at any time in the past?<\/p>\n<p>Linux: in particular, check the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Iptables\">iptables<\/a> output. Might be an old iptables rule still stuck in there &#8211; or even a firewall rule.<\/p>\n<p>Linux + Windows: disable all firewalls, completely.<\/p>\n<p>7. Similarly: do you have any Anti-Virus software?<\/p>\n<p>Disconnect your test machines from the internet, and remove all AV.<\/p>\n<p>AV software can even corrupt your files when they mistakenly think that the binary files used by the compiler\/linker are &#8220;suspicious&#8221; (IIRC, that happened to us with early PlayStation3 devkits).<\/p>\n<p>8. On a related note: security \/ IPS tools installed? They will often insert artificial delays silently.<\/p>\n<p>CHECK YOUR SYSTEM LOG FILES! &#8230;whatever is causing the delay is quite possibly reporting at least a &#8220;warning&#8221; of some kind.<\/p>\n<p>9. (in this case, Cas&#8217;s socket is using SSL): Perhaps something is looking up a certificate remotely over the web?<\/p>\n<p>&#8230;checked your certificate chain? (if there&#8217;s an unknown \/ suspicious cert in the chain, your OS might be trying to check \/ resolve it before it allows the connection)<\/p>\n<p>10. (in this case, Cas is using custom SSL code in Java to &#8220;hack&#8221; it): Get a real SSL cert from somewhere, see if it behaves any different<\/p>\n<p>(I think it would be very reasonable for your OS to detect any odd SSL stuff and delay it, as part of anti-malware \/ virus protection!)<\/p>\n<p>11. &#8220;Is it cos I is custom?&#8221; &#8211; Setup an off-the-shelf webserver on the same machine and check if YOUR READING CODE can read from that SSL localhost fast?<\/p>\n<p>(it often helps to get an answer to &#8220;is it the writer, the reader, both &#8230; is it the hacked SSL, or all SSL?&#8221; etc)<\/p>\n<p>12. (getting specific now, as the general ideas didn&#8217;t help): if you bind to the local IP address instead of 127 ?<\/p>\n<p>13. Howabout reverse-DNS? (again, 4 seconds is in the realm of a failed DNS lookup)<\/p>\n<p>Might be a reverse DNS issue &#8230; e.g. something in OS (kernel or virus protection), or in JVM SSL library, that&#8217;s trying to reverse-lookup the 127 address in order to resolve some aspect of SSL.<\/p>\n<p>I&#8217;ve had to put fake entries into hosts file in the past to speed-up this stuff, some libs just need a quick answer<\/p>\n<h2>Result<\/h2>\n<p>Turns out we were able to stop here&#8230;<\/p>\n<blockquote><p>\nCas: &#8220;Well, whaddya know. It was a hosts lookup after all &#8211; because I&#8217;m using 127.0.0.2 and 127.0.0.3 it was doing a hostname lookup. I added those to hosts and all is solved\n<\/p><\/blockquote>\n<blockquote><p>\nMe: &#8220;(dance)&#8221; (yeah. It was skype. The dance smiley comes in handy)\n<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>Cas (@PuppyGames) (of PuppyGames fame &#8211; Titan Attacks, Revenge of the Titans, etc) is working on an awesome new MMO RTS &#8230; thing. He had a weird networking problem, and was looking for suggestions on possible causes. I used to do a lot of MMO dev, so we ran through the &#8220;typical&#8221; problems. This isn&#8217;t [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[34,20],"tags":[],"_links":{"self":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3216"}],"collection":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/comments?post=3216"}],"version-history":[{"count":3,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3216\/revisions"}],"predecessor-version":[{"id":3219,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/posts\/3216\/revisions\/3219"}],"wp:attachment":[{"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/media?parent=3216"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/categories?post=3216"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/new.t-machine.org\/index.php\/wp-json\/wp\/v2\/tags?post=3216"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}