diff options
author | wjt <wjt@web> | 2015-11-05 03:37:43 -0800 |
---|---|---|
committer | gypsy <iki-gypsy@freedesktop.org> | 2015-11-05 03:37:43 -0800 |
commit | 6509e0a0e4aed049ec40d42df583ab7cc45ec5cb (patch) | |
tree | 9d1649801765cadeec87731e79ca61fc8f7cf419 | |
parent | 0b411fe1f7c5dc2dbc4fb20653f2021babffd2c3 (diff) |
Import this old page
-rw-r--r-- | why-not-gpsd.mdwn | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/why-not-gpsd.mdwn b/why-not-gpsd.mdwn new file mode 100644 index 0000000..a74e90b --- /dev/null +++ b/why-not-gpsd.mdwn @@ -0,0 +1,190 @@ +Why Should You Use Gypsy over GPSD +================================== + +### (Or what I see as the problems in GPSD and how Gypsy solves them) + +Gypsy and [GPSD](http://gpsd.berlios.de) share the same problem space: +multiplexing GPS data from one device to many clients. So why was Gypsy +written from scratch instead of working on GPSD and implementing Gypsy +as an extension of the original GPSD? In this document I hope to explain +the flaws in GPSD at a design level and at the level of users of GPSD +(both users of the program and of the API) + +One major design decision made by the GPSD team is that there should be +no memory allocation functions."Don't Use Malloc" is one of the bullet +points in the contribution guidelines +(http://gpsd.berlios.de/hacking.html\#malloc). + +> The best way to avoid having dynamic-memory allocation problems is not +> to use malloc/free at all. The gpsd daemon doesn't (though the +> client-side code does). Thus, even the longest-running instance can't +> have memory leaks. The only cost for this turned out to be embedding a +> PATH\_MAX-sized buffer in the gpsd.h structure. +> Don't undo this by using malloc/free in a driver or anywhere else. + +This cost analysis is not quite true. It means that all arrays must be +preallocated even if the memory is not used for the program at all. +There was, at one point, an array of 1024 device structures which +allowed for 1024 devices to be connected. This whole array was allocated +even if there was only one device (which is a more common case than +1024). Each structure was 20K, which meant there was about 14meg wasted. +Recent versions of gpsd have reduced this count to only 4 structures, +which is only a waste of 60k or so in the common case. While this isn't +such a terrible waste any more, it is still a bandaid over the problem +rather than a solution. Rather having a sensible memory allocation +strategy would make the code less complicated and mean that there was no +wasted memory at all.\ + Using statically allocated buffers is not in itself bad, Gypsy uses +them in certain places in the code, but its not for fear of leaking +memory, its for speed in the NMEA parsing code which has many small +string operations run many times a second. In code like this, mallocing +small pieces of memory to free them a few lines later is a minor +performance hit and fragments the memory which always annoys the memory +manager. + +GPSD is designed around the idea that it can be accessed remotely. It +sets itself up as a server on port 2947. By default, as of recent +versions, the behaviour is only to allow connections from the local +machine, but the functionality is still there if needed and local +connections are treated the same as remote connections.\ + The problem is I have a hard time coming up with use cases for this in +either general use cases for GPS devices, or the use cases GPSD was +designed for (http://gpsd.berlios.de/hacking.html\#audience). But +because of this useless feature (which is turned off by default) the +common use case is made more complicated because of the primitive IPC +that GPSD needs to use to support it. + +GPSD was written originally in 1995, back then there were few options +for sane IPC (CORBA being rather heavyweight) and using TCPIP sockets +might have been the best option. However, nearly 15 years later, we have +a very successful IPC protocol in D-Bus which provides the things that +GPSD's string and socket based protocol lacks such as type safety.\ + GPSD works that your client opens a socket to the server and sends it a +command. The commands are currently all letters, although at the time of +writing there is only one letter left unused and so a new format is +being discussed. GPSD replies to every letter with a string. Each +parameter in the string is separated by (what appears to be a random +number of) spaces. The Y command is separated by spaces, except for the +quads which are separated by commas. + +These inconsistencies make it awkward to parse by hand and although +GPSD supplies libgps which handles this for you, as we shall see, it has +issues of its own which make it, in my opinion, a less optimal solution. +The proposed version of the GPSD message protocol currently allows for +multiple letter commands and for multiple line responses. This again +adds to the complexity of parsing, which is all something that a proper +IPC system such as D-Bus provides. + +GPSD provides a client library called libgps which simplifies writing +client programs that interface with the daemon. This library handles all +the parsing of the GPSD replies and passes the client a structure with +the values filled in. + +There is both a push and a pull method of accessing the GPS data. In +both methods the user sets a callback function. The push method is done +via threads and the callback is called in a separate thread whenever the +data is received from GPSD. In the pull method, the client calls +gps\_poll and the program blocks until data is available. When data is +available the callback is called and the program continues. + +The first problem is that the options for a programmer are either +blocking or threads. This is fine for a non-interactive console program, +but for GUI programmers blocking calls are a big no no. Every blocking +call potentially freezes the UI. On the other hand in many GUI toolkits +using threads is awkward and no GUI operations may happen from a +secondary thread. Again this complicates the programs using the API.\ + The second problem with the API as it stands is that there is no way to +pass data to the callback meaning that any data needed by the callback +must be a global variable. Again in a simple non-interactive console +program global variables are not too big a deal, but for a GUI program +they are frowned upon. + +Thirdly the API has no concept of objects. Only one callback can be +registered for each of the methods (one for the thread method, and one +for the poll method).This again means that the one callback has to do +everything that needs to be done in the program related to GPS +functions. While again it is possible, it complicates object oriented +programs and breaks the encapsulation of data. + +GPSD is designed to be run at system start, and stopped when the system +is shutdown (or for USB/bluetooth hotplug devices started when that +device is plugged in or removed). If a client is started before GPSD is +running (for example a GPS applet is started before the BT device is +connected), then the only way for it to know that GPSD is for it to +attempt to connect to the GPSD socket and keep trying every so often +until it succeeds. This makes gpsd client programs very busy, always +having to wake up to check to see if it can connect and on a system that +runs on batteries having processes that can't sleep very often is a bad +thing that drains away the battery. + +Because GPSD is designed to always be running and always report fix +data, there is no provision for turning it on and off, except by killing +the process. For systems that try to minimise processor usage while the +device is idle, this makes it hard for programs, as they have to either +be listening to GPSD emitting data, or trying to connect to the socket +to see if GPSD has started up again. + +Also with regards to clients being woken up, even when GPSD is running +clients get notified about everything, even if they don't care about it. +GPSD emits a new fix on every NMEA sentence received, which for most GPS +devices is about 5 a second and each time the clients are all woken up +even if they don't care about the data that has changed. GPSD has no way +for clients to say that they are only interested in position data, or +only in whether the device has a fix or not. Even if the GPS unit is +stationary, satellite data is constantly changing, and the clients will +be woken up on every message. + +Finally, and this may seem like a picky point, but the code is filled +with comments that lint can check its perfectness. The problem, to me, +is that all this just clutters the code and makes it harder to read and +understand, but like I said, this is just a personal thing. + +How Does Gypsy Solve These Problems? +==================================== + +GPSD feels like it was written with no real applications in mind, that +libgps was an after thought and it provides the bare minimum required to +access the daemon and the daemon was not designed with how clients might +want to use the data. Gypsy on the other hand was born out of +frustration with the way GPSD did things and so how applications might +want to use the GPS data was the driving force behind its design.\ + Gypsy was written around D-Bus. D-Bus provides a powerful signalling +system where clients register their interest in certain signals with the +bus, and they are woken up only when that signal is emitted. Clients do +not have to poll to find out if data has changed or whether the daemon +is running. If the signal watches are added before daemon starts, then +the only thing that happens is that they won't do anything until the +daemon starts. + +Gypsy also provides finer grained signals. There are currently five +different signals that a client can listen for: + +- PositionChanged - Emitted when latitude, longitude or altitude are + changed +- CourseChanged - Emitted when the direction, speed or climb change +- SatellitesChanged - Emitted when some part of the satellite data has + changed +- FixStatusChanged - Emitted when the GPS gets or loses a fix +- ConnectionChanged - Emitted when the GPS device is connected or + disconnected + +With these different signals, a client which is only interested in the +whether the GPS has a fix or not only needs to connect to the +FixStatusChanged signal and it will not be woken up if the satellite +position changes, only if the fix status changes. This allows processes +to sleep a lot more. + +Even though the GPS device is constantly sending Gypsy data, Gypsy +checks whether or not the data has changed before emitting a signal. So +if, for example, the device is stationary, no PositionChanged signals +will be emitted until the device starts to move again, once more +allowing programs to sleep more often. + +Using D-Bus allows the API to be combined with main loops using the +D-Bus object bindings. Gypsy comes with libgypsy which is a GObject +binding for the D-Bus protocol allowing Gypsy to be used in a GObject +based system such as Gtk+ or GNOME. Other object bindings could be +written to integrate Gypsy with QT and KDE for example. + +Hopefully with Gypsy, we can great a much more powerful location-aware +system for modern desktops. |