Website Review
What is DelphiTools.info?
DelphiTools.info is the home site for a small collection of Pascal and Delphi developer tools, best known for SamplingProfiler, a free sampling profiler for Delphi code, and DWScript (Delphi Web Script), an embeddable scripting engine for Delphi applications. The site also carries optimization and coding tips and news about its projects.
H3. What you'll find there
- SamplingProfiler — a profiler that samples your running program rather than instrumenting every line, so you can find hot spots in real workloads with relatively low overhead.
- DWScript — a Pascal-style scripting language you can embed in a Delphi host application to let users or configurators extend it without recompiling.
- Other Pascal tools and news — smaller utilities plus posts about performance work, including recent updates to a fork of DelphiCodeCoverage that add an AI-oriented "Code Coverage Gaps" report format aimed at reducing token use when an assistant helps improve unit test coverage.
H3. Who it's for
Delphi and Object Pascal developers doing performance work or adding scripting to a desktop application. If you write C#, Java or Python, the profiler and scripting engine won't apply to you; the general profiling ideas may, but the tooling is Pascal-specific.
H3. Practical next step
If you're chasing a slow Delphi build, download SamplingProfiler and profile a representative workload first — sampling profilers are most useful when you don't yet know where time goes. If you already suspect a specific routine, a stopwatch or manual timing may be faster than setting up any tool.
For comparison, Delphi's own IDE bundles limited profiling, and commercial options exist; a free sampler is a reasonable starting point before paying for anything. General Delphi community resources include Embarcadero for the IDE itself and GitHub for source and issue tracking of community tools.
How do I use SamplingProfiler to find performance bottlenecks in a Delphi application?
SamplingProfiler is a free sampling profiler for Delphi. Rather than instrumenting every routine, it periodically captures the call stack while your program runs, then aggregates those snapshots into a statistical picture of where time is spent. That makes it good for finding hot spots in a running application with minimal overhead, and weaker at giving exact per-call timings or counts.
A practical workflow
- Build with debug information. Sampling profilers resolve addresses to unit, class and method names using the compiled symbols, so a build with debug info (and without heavy optimization stripping that mapping) gives far more readable output.
- Reproduce a realistic workload. Launch the app, attach the profiler, then perform the slow operation — load the large file, run the report, process the batch. Sampling only sees what actually executes.
- Capture for long enough. A few seconds of sampling may be too few snapshots to distinguish a real hot spot from noise. Let the slow path run repeatedly.
- Read the aggregated view, not a single sample. Look for methods that appear consistently across many snapshots and across the whole call tree, including their callers and callees.
- Fix the biggest item, then re-measure. Optimization without a before/after comparison tends to move cost around rather than remove it.
Interpreting what you see
Sampling gives you a relative distribution of time, so treat the results as proportions, not absolute milliseconds. Two traps are common:
- A method that appears often may just be called often, not be slow. Check whether the cost sits in that method itself or in something it calls.
- Inlined or optimized-away code can distort the picture. If a routine you expect to see is missing, the compiler may have folded it into a caller.
For a concrete case: an application that feels sluggish when opening a large project might show most samples inside a parsing routine — but drilling into its callees may reveal that the real cost is repeated string concatenation or a lookup in a linear list. That distinction determines whether you rewrite the parser or just change a data structure.
Where it fits alongside other tools
| Tool type | Best for | Trade-off |
|---|---|---|
| Sampling profiler | Finding hot spots in a running app | Statistical; no exact call counts |
| Instrumenting profiler | Precise per-call timing and counts | Higher overhead; needs rebuilds |
| Code coverage | Finding untested paths | Says nothing about speed |
DelphiTools.info also hosts DWScript and, per its recent news, an AI-oriented "Code Coverage Gaps" format in a fork of DelphiCodeCoverage — useful if your next step after profiling is strengthening tests around the code you are about to change. See DelphiTools.info for the profiler itself and related Pascal tooling.
Next step: pick one operation your users complain about, profile it end to end, and write down the top three methods by sample share before you change any code. That baseline is what tells you whether your fix worked.
What is DWScript and how does it differ from standard Delphi code?
DWScript is an open-source scripting engine for Delphi and Free Pascal, hosted at DelphiTools.info. It lets a Delphi application run Pascal-like scripts at runtime — supplied by users, stored in config, or edited in a built-in script editor — without recompiling the host program. It is also the engine behind the site's own Pascal tooling, so the same maintainer's sampling profiler and related utilities share its lineage.
How it differs from standard Delphi code
| Aspect | Standard Delphi code | DWScript |
|---|---|---|
| When it runs | Compiled ahead of time into native executables | Interpreted (or bytecode-executed) at runtime from text |
| Deployment | Requires recompilation and redeployment to change | Scripts can be edited and reloaded while the app runs |
| Language surface | Full Object Pascal, RTL/VCL/FMX, platform APIs | A Pascal-family subset plus script-oriented extensions |
| Typical author | The application's own developers | End users, integrators, or technical staff customising behaviour |
| Access to the host | Direct | Only through what the host application deliberately exposes |
The practical consequence is the trade-off you are buying: DWScript gives you late binding and user extensibility, at the cost of execution speed, of full language and library compatibility, and of a new security surface — scripts are code, so sandboxing and permission limits matter. If your logic must be fast, touch the OS directly, or ship as a single compiled binary, plain Delphi is the right choice. If your users need to change rules, formulas, or workflows without waiting for your release cycle, a scripting layer earns its keep.
A concrete scenario
Consider a Delphi desktop product for engineering calculations. The core solver, UI, and data access stay compiled. The per-customer formulas, validation rules, and report templates live in DWScript files the customer's own analyst can edit. You expose a small set of host objects — say a material database and a unit converter — and nothing else. Upgrades to the solver ship as a new executable; rule changes ship as a text file.
Deciding
Choose DWScript when runtime flexibility is a product requirement and you are willing to design and maintain the host API boundary. Stay with compiled Delphi when performance, full library access, or a closed deployment matter more. A useful middle step: prototype one real customisation your users currently request, and see whether the scripting boundary stays small enough to be safe and fast.
For the engine itself, its samples and its integration notes, start at DelphiTools.info. For the host compiler and language baseline it extends, see Embarcadero.
How can I generate an AI-optimized code coverage report with DelphiCodeCoverage?
You generate the AI-optimized report by using the "Code Coverage Gaps" format (.ccg) in the DelphiTools fork of DelphiCodeCoverage. That format was added specifically to make coverage output cheaper and easier for an AI assistant to consume, so it is the file you hand to the model when asking it to improve unit test coverage.
What the .ccg format changes
Standard coverage reports are built for humans: they list every line, every class, every method, with full paths and repeated structure. Feeding that to an AI burns tokens on lines that are already covered. The .ccg format instead emphasizes the gaps — the code that is not covered — and trims the surrounding noise, which is where the token savings come from.
Practical workflow
- Build and run your tests with coverage instrumentation enabled, as you normally would.
- Produce the coverage output, and select the Code Coverage Gaps (
.ccg) output rather than a full HTML or XML report. - Give the
.ccgfile to your AI assistant along with a request such as "write tests that close these coverage gaps." - Review the generated tests yourself before committing; coverage gaps tell you where code is untested, not what the correct expected behavior is.
That last point is the real trade-off. A gap report is compact precisely because it omits context, so the AI may invent assertions that match the current implementation rather than the intended behavior. Treat its output as a first draft.
Decision criterion
Use .ccg when your goal is an AI-driven test-writing loop and token cost matters. Use a conventional human-readable report when you need to review coverage with your team, track trends over time, or satisfy an audit — those formats carry the detail people expect.
A concrete scenario
A Delphi team has a large legacy unit with low coverage. Instead of pasting a full HTML report into a chat, they export the .ccg file, ask the assistant to propose tests for the top uncovered methods, then run those tests locally. If a proposed test fails, that is often a signal the code — not the test — is wrong.
For the fork itself and related Pascal tooling, see DelphiTools.info. For the upstream project, see Delphi Code Coverage on SourceForge.
What are some practical Pascal optimization tips for improving application speed?
Practical Pascal optimization starts with measurement, not guesswork: profile a release build under realistic input, fix the top one or two hotspots, then re-measure to confirm the gain. Most speedups come from better algorithms, fewer allocations, and less I/O — not from micro-tweaks.
Where to look first
- Algorithmic cost: replacing an O(n²) scan with a hash lookup or sorted index usually beats any compiler setting.
- Allocation churn: reuse objects, buffers and strings; prefer
SetLengthon an existing buffer over repeated concatenation in loops. - String handling: build output with a
TStringBuilderor a preallocated buffer instead ofResult := Result + ...inside loops. - I/O and queries: batch database calls, avoid per-row file opens, and cache repeated lookups.
- Data layout: pack hot records, use contiguous dynamic arrays, and keep frequently accessed fields together to improve cache behaviour.
- Bounds and checks: keep range/overflow checking on while developing, then evaluate disabling them only in proven hot paths.
- Compiler settings: test optimisation and inlining settings on a release build, and verify with benchmarks rather than assuming.
Profiling in practice
For Delphi work, a sampling profiler is the low-friction option: it attaches to a running program and periodically records call stacks, so it shows where time is actually spent without instrumenting every routine. DelphiTools.info hosts SamplingProfiler, a free sampling profiler for Delphi, alongside DWScript and other Pascal developer tools. If your project mixes Pascal with scripting, DWScript is worth knowing as the same author's embeddable Delphi Web Script engine.
A concrete scenario: a desktop app feels slow when opening a large customer list. Rather than rewriting the grid, profile a release build while opening that list. If the sampler shows most samples inside a sort comparator or a per-row database query, fix that path first — for example, sort once and page the results, or fetch the whole result set in one query. Re-profile afterwards; if the hotspot has moved, you have a new target.
Deciding what to change
| Symptom | Likely cause | First move |
|---|---|---|
| Slow with large inputs, fine with small | Algorithmic complexity | Change data structure or indexing |
| Steady slowdown over time | Leaks, growing lists, unbounded caches | Cap caches, free objects, check ownership |
| Spiky pauses | Allocation or GC-like churn, large string builds | Preallocate, reuse buffers |
| Slow startup | Initialisation, file or registry reads | Defer work until first use |
Next step: pick one user-visible slow operation, profile it on a release build, and write down the top three routines by sample count before changing any code. That list becomes your optimisation backlog, and it keeps effort pointed at changes you can actually verify.
How does the DelphiCodeCoverage 'Code Coverage Gaps' format save tokens when using AI to improve unit tests?
DelphiTools.info describes a .ccg "Code Coverage Gaps" format added to a fork of DelphiCodeCoverage, explicitly aimed at reducing the number of tokens an AI assistant has to read when you ask it to improve unit-test coverage. The saving comes from what the format leaves out rather than from compression: instead of feeding an AI a full coverage report listing every unit, class and line — including the large majority that are already covered — the gaps format is structured around the code that is not covered, so the model reads a short list of targets instead of a complete map of your codebase.
Why that matters in practice
Coverage tools normally emit detailed per-line or per-method records for the whole project. For an AI workflow, most of that is dead weight: the assistant only needs to know which routines lack tests and where they live. A gaps-oriented file reduces input tokens roughly in proportion to how much of the code is already covered, so a project at high coverage benefits most. Fewer input tokens means lower per-request cost and less chance of the model losing the relevant detail in a long context.
A concrete scenario
Suppose a unit has 40 methods and 34 are tested. A conventional report hands the AI all 40 with hit counts; a gaps report hands it the six untested ones. You then ask for tests covering those six, and the assistant works from a focused list rather than scanning and filtering a full report — which also reduces the risk of it writing redundant tests for code that is already covered.
Trade-offs to weigh
- The format is only as good as the coverage run behind it: stale or partial coverage produces a misleading gap list.
- It is optimized for AI consumption, not for human review or historical trend reporting, so you may still want the standard report for dashboards and regressions.
- The page notes these enhancements were pushed to a fork, with uncertainty about whether the original repository is still maintained — so check which fork or version you are actually running before relying on the format.
- Token savings shrink as coverage approaches completeness, and disappear if gaps are scattered across many files, since file paths and context still cost tokens.
Next step
Run your coverage tool once, generate both the standard report and the gaps file, and compare their sizes. If the gaps file is dramatically smaller, make it the artifact you attach when prompting an AI about test coverage, and keep the full report for your own review.
For the tool itself and related Pascal utilities, see DelphiTools.info.
User reviews (0)