Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Plotting GPS data

Sometimes going out for just a walk isn’t that easy and some extra motivation is needed. Luckily I had just that extra: going for a walk allowed me to get some rather important real-world data for the GPS tracking service I have been working for quite some time.

During those walks I had the idea to further use the recorded data. The forest was filled with paths and I thought it’d be great to map those. And maybe even have some kind of heatmap of the most traveled routes!
Work, studies, gaming and general procrastination kept me busy, but here it finally is:

Investigating TCP timeouts

As hinted by an earlier post, one of my latest work projects was a building a WebRTC based video streaming system. This system features a Websocket backend server handling the client sessions and signaling, written in Python with Gevent. My co-worker was performing some testing and everything seemed to be working just fine. Except one point he encountered a situation, where the server insisted another client was already connected, when it clearly wasn’t. Even netstat said that the TCP connection was ‘established’.

Some Websocket client connections were arbitrarily staying open even if the browser was closed! I had just added some hooks to the server to better detect disconnected / timed-out clients and a good guess was that I had messed something up. Nope. Debugged the thing for hours but couldn’t find single bug.

That is, until I tried toggling network connections. Being a system targeted for mobile devices, one facet of testing is to check how well it works with different network connections. If the network connection was turned of while the client was connected, the server couldn’t detect that until after about ten to fifteen minutes, even though it was sending keep-alive packets every 20 seconds. Strange indeed.

But maybe it wasn’t, maybe the write call was blocking the specific greenlet? That is an easy thing to test, just dump some stack traces. But nope again. How about if I run the server via strace and try to spot the writes there? It took bit of an effort, but the strace output revealed that the write calls were performed just fine! This is starting to be most troubling…

But then a revelation; write returned EPIPE. After quite a bit of research I had finally found the reason for this behavior: TCP timeouts. Turning off the network connection really did what it did. It turned off the connection without giving the protocol stack time to say its goodbyes. The server then though the client just had a really bad connection and tried resending the queued data with an exponential delay back off per TCP spec. My math didn’t quite match, but in an old thread the total timeout was calculated to be 924.6 seconds with the default TCP parameters. This was quite close to the actual timeout observed with the server.

* * *

I sighed and changed the keep-alive protocol so that timely replies were required instead of just relying on failed writes. Now it works beautifully.

Tl;dr: TCP was just really hard trying to resend data after it detected packet loss, only giving up when about fifteen whole minutes had passed.

Investigating slow startup of a gevent-based server application

Fast iteration time is critical when developing new things, and everything is fine when the server takes half a second to start. But when that server takes ten seconds to start, that's when things get annoying. So annoying that I had no choice but to spend several hours digging around for a reason for that slowdown.

The server in question was a Python/gevent/pywsgi server kinds of which I have been using quite some time now. And this was a new problem, one I had not previously encountered before: of course I wanted to get to the bottom of this.

First I tried to place some strategic print statements here and there, but those didn't help. Next I fired up the debugger and suspended the process during the startup. Nothing low-level blocking socket creation, and gevent has happily running its event loop; can't be its fault. Gevent has always done a great job not blocking anything, so that couldn't be it. (This is where I made a 'mistake', see the last paragraph.)

I was determined that it was something low-level, so it was time bring out the big guns: API Monitor. It could log every low-level API call, and then it would just be matter of digging through them all. And there indeed was some digging to be done. Then finally I found what I was looking for. The gevent event loop really did spin as it should, but the socket began processing data only after a gethostbyaddr-call returned.

That strange character is actually FE 80 00, rest of the address not rendering as a string.


This low-lever function was taking a long time to execute, and was actually executed in another thread, communicating its results via a socket. back to the main thread. For its argument it was given a link-local IPv6 address of (the first adapter from ipconfig) Hyper-V bridge adapter. Maybe due to some kind of misconfiguration or whatever that call took an excessive amount of time.

Now that I knew what was happening I wanted to know why. Intuition brought me to gevent's socket.py wrapper, where I inserted some tracking code to its implementation of gethostbyaddr. That in turn told me that as part of creating the socket the server's environmental variables were initialized. One of these was SERVER_NAME. If it was not already set, it was resolved via getfqdn - which called gethostname and that devil-ish gethostbyaddr. Only after the server name was resolved could the socket begin accepting connections.

Now that I had the general reason I didn't want to bother myself more that I had to. As the mechanism was already there, all it took was to pass environ={'SERVER_NAME': 'whatever'} as a kwargs to WSGIServer.

* * *

Had I though a bit more before letting go of the debugger and starting the API Monitor, I would probably have though about looking at the individual greenlet stacktraces. Those would have clearly told that the getfqdn call was blocking the main server greenlet.

USG documents now public

Having worked on this document for several(maybe even a dozen) hours over the past two years, I feel it’s finally time to let the world see how I have big plans. Big plans that will probably never be fulfilled. Actually I don’t expect to get everything done, but rather see it as something to work towards to.

There is also some videos on my YouTube channel.

* * *

For those unfamiliar with my projects: USG is the newest incarnation of my long-running series of space themed 2D games.

Old versions of The Peli –game project now on video

Had a short discussion about my game project today. Short story shorter, I didn’t have any material to show what is was like years ago.

Now I do. It was surprisingly simple to get most of the versions to run like they used to. The only real challenge was eliminating the dependency for an asset server; at that time one of my interests was streaming patching and bigfiles as in Guild Wars. Of course I had to implement my own version to a ‘real’ game. After some asset hunting and code patching the games successfully loaded local files and I could finally record the videos in question.

Except one. I had some serious issues with font rendering in one of the versions(pygame either segfaults or freezes without error) and in the end had to replace the fonts with placeholder squares; no idea why in broke and no real reason to fix them.

Imported texts from an Old blog

Stumbled upon some blog texts I had written during 2006-2007 to a custom blogging-software. Decided to import them here. Mostly Finnish texts, sorry. Just couldn't let them lie forgotten. Decided not to import comments, if that is even possible. Although there was more of them than here..

But it was bit of a fight, had to figure out the format used by blogger(it is atom extended with some custom fields) and generate that kind of file from my flatfile-db. Had to copy-paste attributes to feed, add generator-tag and the category kind#post -element to entries. That did it, and blogger imported my XML without a hitch.

And then there was more collisions

Been silent as usual, but now I have SVG-based polygon map(Inkscape as preferred editor) and collision detection based on movement vectors(even high-speed objects collide to map).

Collision detection can be run in pure python(only ~120 colls/s on 108 polygon map…), or optionally accelerated with numpy(~10k colls/s) or external c++ app(~140k colls/s(that is almost 4.5M vector-vector pairs per second!) when compiled with vc++ 2010).

All values on single i7 930 thread(my new system(frostfire), with HD5850, 6GB RAM and 24” full-hd display).

Box2d

Been experimenting with pybox2d, not very long, but have some vids:

Progressing on The Peli and introducing LCS

Polygon based map(+collisions) and editor, waypoint editor, particledemo(5k@60fps on TL-58 single thread). PHP&MySQL content management system with versioning(data only, gui is for user to build, as it should be), used in www.dea.fi(my new domain) and Lannukka. To name a few..

Not dead yet!

It has been quiet here, really quiet..

There is not much progress that could be shown to public, as I'v mostly been developing new techniques and rewriting stuff before it has even finished.

But I can tell that in tests I have easily managed to display 10k static, non-animated, objects at 60 FPS. Hundreds, or was it even 1k??, if moving.

Been also experimenting with triangle-based maps, and they seem to be a viable option. But making holes in them is bit trickier.. Of course I could have another, black layer that is drawn on top of the map and checked for collisions, but that wouldn't be efficient in the long run. Pity...

Then there is an IRC-bot, rewrote core in that once already.. But it is good, I'm telling you!

That leads to an another thingy, Lannukka. It's a going-to-be foundation/voluntary association that will someday host lanparties. Now it has mainly just been group/label/tag/... for me and few friends. Oh, yeah, the bot is on our channel, #lannukka@IRCnet.

Then theres also been all kinds of smaller scripts and stuff that programmers can't avoid doing.

Update on The Peli

The Peli is feeling just fine and has once again been re-written, this time Python(what would you except) and Pyglet(aka OpenGL). Now it is tenth or eleventh rewrite, depending on counting.

Features include

  • Better particle effects
  • Background varying throughout time
  • Somehow nicer/uglier UI
  • More speed there/less somewhere else
  • Once-again seeking missiles/AI with agro
  • Revamped heat/shield system, still in progress
  • Minimap
  • State-machine based core(easy pause menus/stuff, but)
  • No multiplaying

DevNews: Quick overview at my current/past projects

It's been quiet, but I'm not dead, yet.

So I've been coding some pretty neat things, some are new(aka pys60(=for Symbian mobile phones)), and some are older(The Peli!):
  • The Peli: Yeah, it's been playable someday(and it was GOOD) including multiplayer, but nowdays it is more and more a testing ground for Anyload(resource streaming system) and in lesser(O.o rly?) role in testing/developing weapon/upgrade system.
  • Tankwars: Yes. Featuring weapons from The Peli.
  • RPC: Worker thread/server study

PyS60:
  • pyCamera: A real-time video streaming application for S60/PC. Server supports unlimited number of clients(in theory).
  • devname _A[ ]memo_book: Hierarchical notes, done in need and as a testing ground for (de)flattening hierarchial data.
  • Vlan_2: Network stumbler for S60.

And some that are usable but unused / deprecated / i_have_found_better_way / OS_app_exists stuff:
  • Filetransfer/browser.
  • chat infrastructure featuring client/server/masterserver/loginserver/encryption with can trust no-one philosophy.
  • Trayer(2)

I am sure there is many more, but one can't remember everything(and that list just featured python projects, no PHP included).

Summary of The Peli's developement

So it has been quiet here and there, but the project is not dead yet. Visuals have not been changed even an inch(well, maybe the weapon system has changed a bit ;), but core has undergone major changes, now being a complete rewrite. Now it is much more modular, and the greatest(and the most advanced) thing is the file loading functionality, streaming file changes from multiple(at least one) servers, keeping itself up-to-date all the time.

Features:
  • Multiplaying(experimental)
  • Multiple weapons
  • AI(with pathfinding)
  • Customisable gui via XML file

Dependencies include:
  • Python(2.4.4)
  • Pygame(1.7)
  • Pyro for online
  • Network connection
  • And maybe some others

More information will be made availiable when I have time to write it.

Public download will be made availiable when requested AND release is clean.