Saturday, February 27, 2010

Plugin Performance

This blog post is for amateur plugin developers. By amateur I mean: some plugin developers are professional programmers by day, and are already familiar with all aspects of the software development progress. For those developers, the SDK is unsurprising and performance is simply a matter of applying standard practice: locate the worst performance problem, fix it, wash-rinse-repeat.

But we also have a dedicated set of amateur plugin developers - whether they had programming experience before as hobbyists, or learned C to take their add-ons to the next level, this group is very dedicated, but doesn't have the years of professional experience to draw on.

If you're in that second group, this post is for you. Explaining how to performance tune code is well beyond the scope of a blog post, but I do want to address some fundamental ideas.

I receive a number of questions about plugin performance (to which the answer is always "that's not going to cause a performance problem"). It is understandable that programmers would be concerned about performance; X-Plane is a high performance environment, and a plugin that wrecks that will be rejected by users. But how do you go from worrying about performance to fixing it?

Measure, Measure, Measure, Measure.

If I had to go crazy and recite a sweaty and embarrassing mantra about performance tuning so that I could be humiliated on YouTube it would go: measure, measure, measure, measure.

If you want your plugin to be fast, the single most important thing to know is: you have to find performance problems by measurement, not by speculation, guessing or logic.

If you are unfamiliar with a problem domain (which means you are writing new code or a new algorithm - that is, doing something interesting), there is no way you are going to make a good guess as to where a performance problem is.

If you have a ton of experience in a domain, you still shouldn't be guessing! After 5 years of working on X-Plane, I can make some good guesses as to where performance problems should be. But I only use those guesses to search in the likely places first! Even with good guesses, I rely on measurement and observation to make sure my guess wasn't stupid. And even after 5 years of working on the rendering engine, my guesses are wrong more often than they are right. That's just how performance tuning is: it's really hard for us to guess where a performance problem might be.*

Fortunately, the most important thing to do, measuring real performance problems, is also the easiest, and requires no special tools. The number one way to check performance: remove the code in question! Simply remove your plugin and compare frame-rate. If removing the plugin does not improve fps, your plugin is not hurting fps.

It is very, very important to make frame-rate comparison measurements under equal conditions. If you measure with your plugin in the ocean and without your plugin at LOWI, the results are meaningless. Here's a trick I use in X-Plane all the time: I set my new code to run only if the mouse is on the right half of the screen. That way I can be sitting at a fixed location, with the camera not moving, and by mousing around, I can very rapidly compare "with code", "without code". The camera doesn't move, the flight model is doing the same thing - I have isolated just the routine in question. You can do the same thing in your plugin.

Understand Setup Vs. Execution

This is just a rule of thumb, and you cannot use this rule instead of measuring. But generally: libraries are organized so that "execution" code (doing stuff) is fast, while setup and cleanup code may not be. The SDK is definitely in this category. To give a few examples:
  • Drawing with a texture in OpenGL is very fast. Loading up a texture is not fast.
  • Reading a dataref is fast. Finding a dataref is not as fast.
  • Opening a file is usually slower than reading a file.
  • You can run a flight loop per frame without performance problems. But you should only register it once.
If you want to pick a general design pattern, separate setup from execution, and performance-tune them separately. You want things that happen all the time to be very fast, and you can be quite intolerant of performance problems in execution code. But if you have setup code in your execution code (e.g. you load your textures from disk during a draw callback) you are fighting the grain; the library you are using probably hasn't tuned those setup calls to be as fast as the execution code.

Math And Logic Is Fast

Modern computers are astoundingly fast. If you are worried that doing a slightly more complex calculation will hurt frame-rate, don't be. One of the most common questions about performance I get is: will my systems code slow down X-Plane. It probably won't - the things you calculate in systems logic are trivial in computer-terms. (But - always measure, don't just read my blog post!)

In order to have slow code you basically need one of two things:
  1. A loop. Once you start doing some math multiple times, it can add up. Adding numbers is fast. Adding numbers 4,000,000,000 times is not fast. It only takes one for-loop to make fast code slow.
  2. A sub-routine. The subroutine could be doing anything, including a loop. Once you start calling other people's code, your code might get slow.
This is where the professionals have a certain edge: they know how much a set of standard computer operations "cost" in terms of performance. What really happens when you allocate a block of memory? Open a file? If you understand everything going on to make those things happen, you can have a good idea of how expensive they are.

Fortunately, you don't need to know. You need to measure!

SDK Callbacks Are Fast (Enough)

The SDK's XPLM library serves as a mediator between plugins and X-Plane. Fortunately, the mediation infrastructure is reasonably fast. Mediation includes things like requesting a dataref from another plugin, or firing off a draw callback. This "callback" overhead contains no loops internally, and thus it is fast enough that you won't have performance problems doing it correctly. One draw callback that runs every frame? Not a performance problem. Read a dataref? Not a performance problem. (Read a dataref 4,000,000 times inside a for-loop...well, that can be slow, as can anything!)

However you should be aware that some plugin routines "do work". For example, XPLMDrawObject doesn't just do mediation (into X-Plane), it actually draws the object. Calls that do "real work" do have the potential to be slower.

Be ware of one exception: a dataref read looks to you like a request for data. But really it happens in two parts. First the SDK makes a call into the other plugin that provides the data (often but not always X-Plane itself) and then that other plugin comes up with the data. So whenI say "dataref reads are fast" what I really mean is: the part of a dataref read that the SDK takes care of is fast. If the dataref read goes into a badly written plugin, the read could be very, very slow. All of the datarefs inside X-Plane vary from fast to very fast, but if you are reading data from another plugin, all bets are off.

Of course, all bets are off anyway. Did I mention you have to measure?

* Why can't we guess? The answer is: abstraction. Basically well structured code uses libraries, functions, etc. to hide implementation and make the computer seem easier to work with. But because many challenging problems are hidden from view (which is a good thing) it's hard to know how much real work is being done inside the black box. Build a black box out of black boxes, then do it again a few time, and the information about how fast a function is has been obscured several times over!

Friday, February 26, 2010

Stutters Fixed (I Hope)

X-Plane 950 beta 1 should fix the stuttering present in 940. The bug was: the more you flew in one area, the worse the stutters would get - they'd clear out if you kept flying forward enough to scroll DSF tiles normally. Anyway, the bug was a book-keeping error based on the new "paged" airports from 940.* Fixed now - thanks to the users who got me a really clean test case to see this.

(Hint for users: if you can duplicate a scenery-related bug by saving a replay, or even if the bug can be reproduced in replay, that's really, really useful to know! It makes the bug much more repeatable, since what scenery is loaded varies a lot with flight path.)

* Before 940 we would load the entire apt.dat file into memory on startup. With Robin receiving new highly detailed airport layouts every day, this was starting to use more and more memory. 940 and 950 will load a litttle bit of information about every airport and take note of the file that contains the layout - then when the sim needs a layout, it goes back to disk to pull up just the one airport in question, saving memory. We "page" the airports into memory only as needed.

Updater Design Decisions

My blog postings have been a little thin - but not because nothing is going on. Rather it's a combination of working on next-gen stuff that is still in heavy development, travel, and (perhaps due to the travel, perhaps due to lack of sleep, or perhaps due to certain forms of Brandy brought on site by a certain British developer who won't be named, but whose handle on the org starts with a P and rhymes with "Cropsman", cough, cough) a minor fever that I've just about recovered from.

A user asked me about the design of the X-Plane updater - so this post is only going to be of interest to the few authors out there who are creating installers for their add-ons and need to update. We try to keep the file formats for X-Plane simple, e.g. "this one folder is your airplane", so that if you don't make an installer, the user won't be overwhelmed with a complex unpack-and-install routine. But if you do need to install or update, well, here's what we were thinking when we developed our installer.

We had a few needs for our installer:
  • It had to be cross-platform to Mac, Windows and Linux.
  • It had to update existing products as well as install new ones.
  • The updates had to be minimal deltas, e.g. a demo can be 600 MB but an update should only be the 30 MB of files that really changed.
  • We wanted the updater to do delta updates from any old version. (Some update systems require installing a number of patches in sequence. We have users who buy the DVD and then update a year later; we wanted to let them update in one shot.)
  • Building the patches had to be really, really fast. We use our updater to publish our betas. So while X-Plane probably has 2-3 major patches in a single year and maybe 5 or 6 bug fix patches, we will (due to betas) cut perhaps 100 or more actual "updates".
  • On that last point, cutting separate updates by platform was a deal breaker, as it would triple the number of updates we had to cut. Having a demo install and an update be the same on the server was a big win.
Some of those needs are pretty specific to Laminar Research, but some might apply to a third party. There are commercial installers that will let you generate patches. If you don't generate a lot of patches, you can probably use existing tools - basically you'll spend a lot less time up front (since the tool set exists) but you might spend more time in the long run cutting separate patches by OS.

One of the first things we decided was to not use server-side technology or special protocol. That is, we don't need any kind of smart servers to run the updater - the updates are just files hosted over HTTP on standard rented or owned apache servers. All of the work is done in the client. We did this for a few reasons:
  • It lets us throw up the install anywhere - we don't have complex needs for what's on the server. Virtually any server will do. (As the company has grown, our server needs have grown too, so this is less of a concern now, but back then we had fewer servers in service, and were buying less overall server capacity.) If a server goes down, we can press another one into service about as quickly as we can move the file set to the server.
  • We're not server programmers. Coding the installer/updater on the client side let us leverage existing company technology, etc.
Here's what we came up with. The basic idea of the installer is very simple. Note that since the installer uses HTTP files, you can "watch" the installer simply by downloading the files that it downloads.
  1. First the installer goes to a master server and gets a "version list", which tells it what it's going to actually get and what (multiple) mirrors are available. This one master file is the only file that must be hosted at X-Plane.com, and it allows us to change a very small file to press mirrors into service.
  2. Installs and updates are actually the same to us - it's a set of files that the user should have once the install or update finishes. This starts with a file directory that lists every file (by path) that needs to be downloaded, as well as its MD5 signature.
  3. The directory also contains the MD5 of every old version of any file in the version, and lists files that have to be deleted to update the version (e.g. the file panel.png used to have MD5 signature 2934b..23abc2 but is now removed).
  4. The client, once armed with the file directory, can now download all files in the directory (install) or compare the existing files on disk to the directory by MD5 and only download changes.
  5. Individual files are on the server in zip form for download and decompression.
That's pretty much it - you could write an installer in a scripting language using a tool like CURL or WGET - it wouldn't be very complex because the installer is really just a clever, painted download+unzip tool.

Dealing With Modified Files

There is a bit of complexity in this design that you might not need for a third party installer: handling modified files. Note that the directory contains the MD5 not only of the current version of the file (to detect when no update is needed and save bandwidth) but also to see when the user has modified a file that is "managed" by X-Plane.

Before the installer overwrites/deletes a file that you own, it compares the file's MD5 to the entire known list of MD5s for the entire version. If this file doesn't match a known old version, it puts up the warning dialog box that you have modified a file that is about to be overwritten.

While we recommend that add-ons use scenery packs and other "safe" ways to customize the sim, this helps detect when a user has gone in and edited the cloud textures in Photoshop, and prevents us from overwriting them without warning.

Wednesday, February 24, 2010

Life Would Be Easier

Life would be easier if the Earth was a big cube.* I was reminded of this yesterday when I discovered (thanks to a bug report from an author) that X-Plane has been drawing objects with slightly incorrect heading for the last who-knows-how-long amount of time.

The bug (present in 945 and going back who-knows-how-long) is that the object's heading can be off by up to 1 full degree clockwise or counter-clockwise. (This maximum error occurs at the north pole - average error for real use cases is more likely to be about 0.35 degrees.) The amount of rotation depends on how the scenery system is shifted.

The case the author sent me was a converted scenery pack, where a pair of parallel runways were modeled partly out of draped polygons (which don't exhibit the bug), but with markings modeled as an OBJ. Depending on the scenery system's "centering" the markings would be a little bit to the left or right of the draped polygon.

A brief aside: do not model your scenery this way! A bug is a bug, and X-Plane 950 beta 1 fixes this problem, but there are a number of reasons not to use a giant OBJ to model your runways.
  • OBJs do not "hug" the terrain, and the Earth is round. You will never really get clean, artifact-free flat surfaces unless they can follow the terrain contour. Even if you "flatten" the terrain, it's not flat - it's constant MSL.
  • The case where I see this more often is with buildings, where authors build every single terminal building in one OBJ. X-Plane only "connects" the OBJ to the ground at one point (0,0,0 in the object). So to get a good ground connection, you need your objects to be smaller, so they can all "sit" on the ground. (Technically they need to be rotated slightly to wrap around the Earth, but for the scale of an airport this error is only about 1/30th of a degree or so - hard to see.)
  • Finally, X-Plane chooses to draw or not draw an object on a whole-OBJ basis. So if you have a huge object, it's always in view (because at any one time some part of it is in view). In fact, even if the object is not in view, the larger the object, the more the "sloppiness" of the visibility check causes false positives. (The visibility check is optimized for speed, so it really answers "this object is probably in view", erring on the side of drawing too much by doing less analysis.) So the bigger your objects, the more they are drawn.
Enough ranting - in this case the scenery was the output of FS2XPlane, and the author hadn't gotten to cleaning the results. Fortunately the interim product showed the rotation bug.

X-Plane 950b1 (in beta now) fixes this problem - rotational alignment of a very large OBJ with a draped polygon should match between X-Plane (with all frames of scenery system reference) vs. WED 1.1 preview 2 pretty much exactly.

*This post is in the long and distinguished tradition of "life would be easier if" musings relating to scenery, e.g. global scenery would be easier if the entire planet was paved in asphalt, cities would be easier if their road grids only ran perfectly north-south and east-west, clouds would be easier if they weren't translucent, and rendering would be easier if nothing on the planet ever was translucent or cast a shadow. So apparently a programmer's paradise is somewhere between "Mad Max" and a Dali painting...

Tuesday, February 23, 2010

Airport PerformanceTip

There's a slight performance win to be had by grouping taxiways by their surface type.

Now clearly if you have to have an "interlocked" pattern of asphalt on top of concrete, on top of asphalt, this isn't an option.

But where you do have the flexibility to reorder, if you can group your work by surface type, X-Plane can sometimes cut down on the number of texture changes, which is good for framerate.

X-Plane will try to do this optimization for you, but X-Plane's determination of "independent" taxiways (taxiways whose draw order can be swapped without a visual artifact) is a bit limited and can only catch simple cases.

For what it's worth, interlocked patterns of surfaces were much more a problem with old X-Plane 6/7 type airport layouts, where the taxiways were sorted by size, and there could be hundreds of small pieces of pavement.

Friday, February 12, 2010

Why Do You Have to Tell X-Plane How Wide a Texture Is?

Some of the newer text file formats for art assets (.lin files, roads, etc.) require you to specify how wide the texture is.

Huh? Why does X-Plane need me to tell it how wide a texture is? Doesn't it know?

Well, first, the answer is: no! When X-Plane builds the roads and draped lines, the texture that is needed may not actually be loaded. It may only be on the todo list of textures that need loading, and if you have orthophoto scenery, that list could be very, very long. There is no guarantee that the texture is loaded before the geometry gets built. If you have a multicore machine, both might happen at the same time!

So the first reason why the road and .lin files require you to declare the size of your texture is: to allow X-Plane to build the mesh on a separate core from the one that loads the texture, for faster loading. Isn't multi-core fun?

There's another reason, and it's a little bit more subtle: you can change the size of your X-Plane textures. Imagine that you get a new graphics card and you decide to "upgrade" your scenery pack. So you double the size of all of your textures, and then go in to photoshop and add more detail.

But if X-Plane were to look at the size of the texture, then all of your .lin files will be wrong! For example, let's say you have a .lin file with a line from pixels 0 to 16 across the texture. When you double the size of your texture, you'd have to go in and change this to be 0 to 32 pixels across the texture.

But here's the trick: since X-Plane gets the size of the texture from you and not from the actual texture, you can just leave your .lin file the way it was - with the old texture size and the old coordinates. X-Plane will do the math out and generate correct texture mappings even though the texture size is double.

In other words, the important thing about texture coordinates is that they are self-consistent, not that they reflect the actual texture size. This is because internally all texture mapping is done in ratios.

(So why not just use ratios in the file format? Try entering the size of 10 or 12 lines as ratios and tell me whether you like it. The ability to enter the line coordinates in pixels is to make it easier to set up the line files from the image file.)

Thursday, February 11, 2010

A Few More Lights

X-Plane 9 has a number of recent features to let you customize the exterior lighting of your aircraft; see the wiki for notes and a sample plane.

X-Plane 940 introduced the concept of parameterized lights to support these features. Here's the basic idea:

Named lights (available for quite a while now) let you add a light billboard to your model that we define. The idea is that since the lights are specified against a real world model (this light billboard should look roughly like a landing light) it lets us upgrade art assets and back the light with the fastest path on the graphics card.

The problem with landing lights is that they are one-size-fits all, and this is particularly problematic for airplanes, where the lights can look quite different in size and angle based on the size of the airplane. Parameterized lights fix this by letting you specify a limited number of parameters in your OBJ. By limiting the parameters that you can set, it means that we can still optimize the light when possible.

I took a few minutes today to round out the list of parameterized lights, and I think there will be 9.46 patch in which we can release them*. When we put 9.46 in beta I'll update the example plane; the new set of lights will give you parameterized control over the navigation and taxi lights, as well as the generics, beacons, strobes and landing lights.

* We have a few small bug fixes we'll roll out in 9.46.

Wednesday, February 10, 2010

Systems Modeling and Physics Modeling

In past blog posts I have tried to contrast two very different different approaches to simulation, which I would loosely call:
  • "Predictive" (or reality-based). Input data comes from real world measurements, and the simulator predicts the expected behavior based on those inputs.
  • "Prescriptive" (or specification based). The input data describes the desired output directly through preset formula.
In particular, when it comes to the flight model, X-Plane is predictive, via blade theory (X-Plane adds up all forces) while FS X is prescriptive (a table describes aircraft behavior).

But - not all of X-Plane is predictive. In particular, the "systems model", which is a loose term for the modeling of electrical systems, hydraulic systems, and a number of other parts of the plane, is actually prescriptive in X-Plane, while the aerodynamics of the plane are predictive.

To illustrate: when your plane takes off, it leaves the ground because X-Plane has calculated and summed all forces and torques on the plane and has found that it has positive lift. You don't program this in - you simply provide a number of parts that, under some conditions, influence the lift calculations. (Wings are good for this, btw! :-)

But when you turn off the avionics master switch, X-Plane does not calculate the electron flow through the wiring harness to the glass PFD. Rather, the PFD is tagged with input data saying it requires the avionics master to be on. The PFD's behavior with respect to the avionics switch is prescribed, not derived. (If we had a true "wiring editor" in Plane-Maker, it would be different - X-Plane would trace electrical routes and see if enough current makes it to the PFD.

In truth the distinction is a little bit fuzzier. For example, the gyroscopes actually do model the spin of the internal gyro (fail the vacuum system and watch them slowly pick up error like in a real plane) and the electrical system does internal current calculations. But in general the systems modeling is a bit of a mix, mostly prescriptive. This is in contrast to the physics of flight, which are completely predictive.

Monday, February 08, 2010

Why Does the Global Scenery Take 6 DVDs?

Periodically I see the question asked: why does the global scenery take up so many DVDs? Or more typically the question is: if it is so big, why is X missing, where X is the detail the user expected to see but did not find.

The size of X-Plane's global scenery is due to two factors:
  1. Some aspects of the scenery are very detailed, and this takes up disk space.
  2. Some aspects of the scenery are computed ahead of time, not by X-Plane, and this takes up disk space.
Big Data

A few data sources make the scenery pretty big:
  • The scenery is generated from 90m SRTM data for the entire world.
  • US scenery includes the entire US road grid.
  • Coastline data is fairly detailed in the US and for most oceanic coasts.
In other words, part of the size of the scenery comes from having reasonably accurate topography and coastlines everywhere.

Precomputation

The other source of file size is that X-Plane precomputes aspects of the scenery to reduce load on X-Plane while you fly. (We do this to improve frame rate.) In particular, the scenery uses a class of algorithms that are expensive to compute, and thus we compute them ahead of time and save the result (using up file space).
  • Land class changes not on a regular grid, but along iregular polygonal boundaries following the shape of the terrain. This produces much more natural terrain transitions in the mountain, but requires more storage.
  • "Auto-Gen" forests and buildings don't follow a grid - rather, they fit into the irregular spaces made by vector roads and water. This fitting process is too slow to run inside X-Plane, so every auto-gen building and forest area must be pre-computed and saved.
Room To Grow

One interesting side effect of saving the end results of building locations ("pre-placement", what X-Plane does) rather than the formula for how to place them ("auto-gen", what FS X does) is that we can make the placement algorithm for buildings significantly smarter without any increase in file size or decrease in frame-rate. Having already eaten the cost of putting every building into the DSFs, we can make those locations better without hurting performance.

That algorithm to pre-place buildings also can have access to source data that isn't available in the final DSF, allowing for effects that might not be possible in an auto-gen system.

Saturday, February 06, 2010

X-Plane Is An All You Can Eat Buffet

I have blogged in the past regarding the rendering settings in X-Plane, but this seems to come up periodically, so here we go again. Invariably someone asks the question: "what computer do I have to buy to run X-Plane with all of the sliders set to maximum?"

I now have an answer, in the form of a question: "How hungry do you have to be to clean your plate at an all-you-can-eat buffet?"

There is no amount of hungry that will ever be enough to eat all of the food at an all you can eat buffet - you can always ask for more. And when it comes to rendering settings and global scenery, X-Plane is (whenever possible) the same way. You can always set more traffic, more birds, more objects, more FSAA.

Now the all-you-can-eat buffet doesn't have infinite amounts of food in the building - just enough that they know that they won't run out. And X-Plane is the same way. There is a maximum if you set everything all the way up, but we try to make sure that no one is going to hit a point where they want more eye candy but they've maxed out the settings. Eat all you want, we've got more.

Why on earth would we set up X-Plane like this? The answer is choice.

If you go to an all you can eat buffet, you can fill up on nothing but potatos, or you can have five pieces of chicken. It's up to you. X-Plane is the same way - you decide if you want objects to be visible farther away or more densely. Would you rather have roads or trees? Birds or high frame-rate? You decide!

Not everyone's appetite is the same, and not everyone's taste is the same. This is very true when it comes to flight simulation. There are huge variations in hardware capability, target framerate (some users don't mind 20 fps, some demand 80 fps) and in what part of the visual experience people care about most (objects vs. FSAA vs. visibility distance, etc).

Given such a heterogeneous environment, the only way to meet the needs of a wide group of users is to present choice, and make sure that we have enough of everything.

So when you go to set the rendering settings, don't think that setting objects to anything less than maximum is like only eating half the steak you bought at a steak-house. Rather, the rendering settings are like picking which food from the buffet makes it to your plate. You choose how much you want based on what you can consume, and you pick and choose what is most desirable to you. And like an all you can eat buffet, don't eat too much - the results won't be pleasant!

945 Is Here

A few days ago Austin made the recently cut X-Plane 9.45 "final" - that is, it is now the version you get when you update or grab a demo. This (hopefully) ends a sequence of 940 patches that represented a mix of fixing last-minute bugs and breaking and then fixing the throttles for a few add-on airplanes.

As always, if your add-on worked in an older version 9 but is broken in 945, please let us know. I believe the compatibility situation with 9.45 is pretty good though.

Will there be a 9.46? I don't know, but I think the answer is: "probably". I found a driver bug (occurs only on OS X) we can work around a few days after 9.45 was cut. We maintain a list of fixes, and when it starts to add up, we'll cut a new patch to address them. Normally a driver bug would get a patch immediately, but from what we can tell, this one is very rare, so we're not going to fire-drill and cut a new patch 1 day after 9.45 went final.

What kinds of bug fixes make it into these "bug fix patches"? To give an example, I received a report that the "clipping" checkbox on instruments is not preserved when you export an instrument as a text file. That's the kind of thing we'll fix in a patch, but we won't cut a new patch immediately for.

Wednesday, February 03, 2010

DSF and WED Precision

I just finished fixing some bugs with WorldEditor and DSF precision. A WED user was seeing draped polygon tiles exporting with alignment error, and the culprit turned out to be DSF precision. This begs the question, how precise are the lat/lon coordinates in a DSF?

DSFs are based on 16-bit coordinates, for a precision of one part in 65536. Now before you go screaming that 16-bit is dreadful, here's the key: those 16-bit coordinates are interpreted within an arbitrary sub-rectangle of your tile, called a "pool". If we only had one pool covering the DSF we'd have 1.5 meter precision. But by having many smaller pools, we can have high resolution within a pool.

All of the current DSF writing tools from Laminar Research are based on DSFLib, and DSFLib will create a number of pools along a pair of offset grids. In practice what this means is that you specify a number of pools across the DSF.

In WorldEditor 1.1dp2 the DSF exporter uses 8 pools. Since a DSF is about 100 km across, each pool is 12,500 meters in size, and the internal resolution of each pool is 19 cm. This is pretty good but there are cases where you can see the limits of precision. The new code (which will be in preview 3 or beta 1) uses 32 pools, for 5 cm precision.

If you use DSF2Text, you can simply use the DIVISIONS command to specify how many pools you want.

WorldEditor's internal representation is 64-bit floating point, which gives precision better than 1 mm.