[Next]
[Up]
[Previous]
[Contents]
[Index]
Next: Index
Up: NannyMUD LPC
Previous: 10. The Boot Sequence
Subsections
11. Tips, Traps and Trix
11.1 On the #pragmas strict_types and save_types
Using #pragma strict_types make life more interesting, which is part
of an ancient Chinese curse. It is for those who code the objects of
the mudlib, and those that like to type a lot of extra code, like to
control their types, and those who think it looks nice (beware that
beauty lies in the eye of the beholder). For most people, it isn't needed.
The
#pragma save_types are only of use in objects that are inherited a lot,
like the lib objects.
11.2 Optimisation
As usual in optimisation, there are two things you must know before you
start:
- 1.
- What to optimise, and
- 2.
- how to optimise that.
In general, you should use as good data structures as possible to save
memory, and as good algorithms as possible to save CPU. Remember that
there is an upper limit to how many evaluated nodes (evals) that can be
used for a piece of code. Apart from that, it is really impossible to
give other than general advice, since details on costs will change between
driver versions. Here are some tips that will probably be valid even in
the future, though:
- Avoid file accesses like the plague!
Accessing the discs is magnitudes slower than accessing memory.
Do not handle files unless you have to.
- Avoid nested loops.
Using nested loops, it is very easy to hit the max evals.
- Avoid loops.
In many cases, the loops can be deferred to the driver. The driver
is much faster doing loops than LPC is. Typical examples are
call_other() on arrays of objects, and sorting of arrays.
- Avoid expensive function calls in tight loops.
Calls to functions has some overhead, especially if large data
structures are sent to, and modified within, the functions.
- Optimise your loops.
Be sure that the code you have inside a loop must be there. Move
loop invariant code out of it.
- Mappings are sorted, 1.
This means that looking up a key in a mapping is faster
than searching for it in an array, even when using the efun
member_array().
- Mappings are sorted, 2.
For integers, the sort-order is recognisable to humans as ascending
order. This can be used to sort an array by doing
'm_indices(mkmapping(arr,arr))'
- Mappings are sorted, 3.
Using this fact with manufactured keys can be faster than using
'sort_array()'.
- Avoid subscripting, 1.
Use 'foreach' whenever you can get away with it. It is the fastest
loop construct available in LPC.
- Avoid subscripting, 2.
Don't pick out single elements from large arrays or mappings. It
takes forever.
- Avoid sprintf.
Don't use 'sprintf()' when a a simple 'write()' will do,
- Use sprintf.
Use 'sprintf()' instead of building presentation strings by
concatenating things in loops.
- Use continue.
Use 'continue' to short-circuit your loops as early as possible.
- Use 'break'.
Use 'break' to exit loops etc. as early as possible.
- Use '||' operators to set defaults.
The construction 'foo = foo || "default"' is faster than
'if (!foo) foo = "default", and just slightly less readable.
- Use 'switch - case' instead of 'if - elseif'.
It is faster, and easier to read.
- Don't change size of your arrays.
When you change the size of your arrays, new memory has to be
allocated. If you do this more than once, you could consider
allocating the array in advance using 'allocate()'.
- Use inheritance.
Don't re-invent the wheel; if there is a lib object that you can
use, do so. If you can use it with a few simple modifications, do
that. If there isn't a lib object you can use, talk to an arch
about it.
11.3 Three Keys to Successful Creating at NannyMUD
There are three things you need in order to have a successful career as
a creating wizard at NannyMUD:
- Know thy LPC.
Without the knowledge of how things happen in LPC, you will at best
be able to fill in templates.
- Know Thy Lib.
The lib contains a lot of standard objects. They offer a wide, and
supported, selection of functionality and features. You need to get
familiar with those in order to avoid re-inventing everything. If you
do know the lib, you can make a passable area just by filling in
templates.
- Know The Rules.
Since NannyMUD has been around for a while, about every mistake has
been done here. The rules collection reflects this by setting limits
on things. Every rule is there because it is has been shown to be
needed. You need to have some knowledge of them, or your creations
will never make it into the game.
11.4 Some Common Mistakes
- Forgetting the inherited object.
Often, people forget that they have inherited an object, and that
the inherited object needs a call to reset(), too. Even worse is
when you overload init(). Use the :: operator to call functions in
the inherited object, or objects.
- Trusting results from efuns.
Yes, at times efuns like environment(), this_player(), and even
this_object() will return a zero, and rightly so. Beware, and be
prepared to handle this.
- Doing 'call_other()' on a zero.
Before using 'call_other', be sure that the object in which you
call the function does exist. Also be prepared to have code to
handle the case when it does not exist, in a meaningful way.
- Not initialising your arrays and mappings.
Using the index operator, `[ ]', on a zero gives a run-time error.
Remember that all variables are automatically initialised to zero,
and that zero is not a valid array, nor mapping. Be sure that you
do initialise them to ({}) and ([ ]) respectively, at least.
- Providing the wrong number of arguments.
When using the #pragma strict_types,
you have to provide the right
number of arguments when calling a function, unless it has been
declared with the type modifier 'varargs'.
- Providing wrong types to operators.
People will, sooner or later, call your functions with the wrong data
type on the arguments. If your code relies on correct arguments being
sent to it, rather than checking what actually were sent, it will break
sooner or later.
- Exceeding index ranges.
You should avoid writing code that will try to access arrays outside
of it's index, 0..s-1, where s is the number of
elements in the array.
- Not exiting the function after destructing the object.
When an object destructs itself, the statement to that effect should
be followed by an immediate exit from the function.
- Trusting a player to be active.
Beware that players can suddenly quit, go link-dead (LD), leave the
location, die, etc. The LD case is especially obnoxious and hard to
safe-guard against; all the others can be easily handled, and should.
- Using move_object() when you mean transfer().
The efun transfer() should be used when you need checks for weights,
i.e. when moving objects to and from players. To and from everything
else, use move_object().
- Trusting player input.
When the argument to your functions is based on player input, be sure
to check that you get any, and check what you get. In particular,
beware the player who on purpose gives negative arguments.
- Believing that the MUD is multi-threaded.
The MUD is a single-threaded process: when your code is run, no other
is.
- Using delay loops.
Believe it or not, some people have actually created empty loops to
create delays. Don't do that, use 'call_out' instead.
[Next]
[Up]
[Previous]
[Contents]
[Index]
Next: Index
Up: NannyMUD LPC
Previous: 10. The Boot Sequence
Mats Henrik Carlberg
1998-03-25