I. | What does this module do? |
II. | Using the module |
The "Profiler" is a NWNX module that spits out statistics about running scripts. It shows how often a script has been called, how much time it took to complete, and gives some overall statistics. This is especially useful if you want to identify scripts with performance problems, or want to determine which scripts should be put in the script cache.
You do not need to put any special code in your scripts.... just copy the nwnx_profile.dll in your NWN directory, load up a module, and check the logs.0 directory for nwnx_profile.txt. Every 10 seconds, this module will append the current statistics into this file, so remember to re-open it once in a while to get updated statistics.
Licence
This module is distributed unter the terms of the GNU
GENERAL PUBLIC LICENSE included in licence.txt.
The original version 1.0 overlooked some scripts. First of all, nested scripts weren't correctly logged. A script which called another script with ExecuteScript() wasn't accounted at all. Props go out to FastFrench for pointing this out.
Also, there was another script constellation that also went wrong in the previous version. When you call a function directly with ExecuteScript(1.0f, MyFunction()), not the whole script, but only a "part" of the script is executed, namely just that function. Version 1.1 takes this special case into consideration, too. "Partly" executed scripts are denoted with a '>' sign before the script name.
The timeing measurement should be more accurate now. Previous versions took the time it took for a script to be loaded by the server into memory into account (either from disk or from the disk cache), but since NWN can cache scripts now, the profiler only measures the real execution time. This means you will get somewhat lower accumulative times compared to previous versions.
Note that scripts called via DelayCommand (e.g. DelayCommand(1.0f, ExecuteScript("myscript", OBJECT_SELF))) are counted twice, one time as a normal script call, and a second time as a "partly" called script. Thus when the line above is executed ten times, you will get two entries for this script: 10 times "myscript" and 10 times ">myscript". This is due to the way the NWN engine works and I currently do not know of a way to code around it.
Logfiles have a fixed size limit now, which can be set at compile time. In the binary distribution, a hard limit of 512 KByte has been chosen. If the log file exceeds this limit, it will be emptied and the profiler starts again with a clean file.
During my tests, I found that pathfinding can be a big performance hog in NWN, especially under circumstances where creatures are blocked in a somewhat narrow space or where they are repeatedly trying to pathfind across several areas. Therefore, this updated version supports profiling the two pathfinding routines in NWN (that's a bit of a oversimplification, but that's how you can think of it).
There are two types of NPC pathfinding in NWN:
Pathfinding can't be totally avoided of course, but you should be able to considerably reduce CPU cycles wasted by useless pathfinding in your module. Useless pathfinding can happen for example, when you place a NPC inside a small confined space, e.g. four fence placeables laid out as a square. It can also happen if a NPC does waypoint walking and tries to reach a waypoint that exists in the module, but is not reachable on foot. You will see excessive pathfinding events in the log file in these cases.
For tile pathfinding events, the name of the area where the pathfinding is happening is written to the log file and marked with a dollar ($) symbol. For cross area pathfinding, it's the tag of the creature marked with an at (@) symbol.
Another new feature: Updated entries are marked with a star (*) symbol. Previously, it was very hard to find out what scripts caused the delta in runtime between two logging events. Now it's easy to see which scripts eat up your valuable CPU cycles.
Support for NWNX.INI file has been added. There are two options that can be configured:
[PROFILER] MaxLogSize = 512 ; in KByte LogLevel = 1 ; 1=overall statistics, 2=full script callstack