fseek() in File::append() was invalidating the file buffer for each call
to append(). Better handling improves "import" performance test by 9%,
45% in "commit", on a system with a spinning disk.
This performance problem affects all operations where
{pending,completed}.data are rewritten. During normal operation a
garbage collection can be enough to trigger it. On storage with high
latency, e.g. networked, this previously took 20 seconds and more.
Reduce the amount of copies necessary for TDB2::gc() by moving the GC
processing to the Task object source - TF2::load_tasks().
This entangles TDB2 and TF2 more than previously, but leads to huge
performance benefits:
- "next" performance test down 21%
- "list" performance test down 11%
- "all" performance test down 4%
- "export" performance test down 9%
The "gc" measurement is down 96% for all performance tests. This is a
result of moving the actual processing into TF2::load_gc() and not
measuring the time taken by that function as "gc" time.
- Make the Task object's interface more explicit by removing the
std::map inheritance.
- Using this more explicit interface, remove unneeded ctors in order to
allow the compiler to "Do The Right Thing"(tm).
This leads to a performance improvement of 12% in the "add"
performance test, and 7% for "import".
- Improves "task import" performance test on test machine further from
13s to 1.9s.
- Active only during "task import". Might be worth using during other
mass lookups like "task sync", or could even be a good default.
- Switched Nibbler::getUUID to Nibbler::getPartialUUID, which caused partial
UUID mathcing to fail sometimes.
- Changed precedence to search for UUID before ID, which solves the numeric
UUID problem.
- Use variadic templates, with a slight twist for properly supporting
Taskwarrior's l10n strings.
- Adjust code that relied on implicit type conversion which led to
problems with template instantiation.
- Move some functionality out of format() in order to keep it generic.
- Fix completed/deleted tasks getting an ID when GC is going to be run,
previously resulting in invalid IDs being displayed in reports that
show non-pending tasks.
A side effect of this fix is that it is sometimes not possible to
filter by ID when running a report right after calling done/delete.
This problem existed before; this change makes it happen on the first
report instead of the second, so it is more consistently broken.
Commands that modify tasks are not affected, making this an annoying
yet harmless defect.
- TDB2::dependency_scan() is run before GC, so we need to check both
tasks in a dependency chain for their status before setting the
blocking/blocked flag to true.
- Removed the ability for hooks to add tasks, or modify tasks that are outside
the context of the current event. This makes hooks a local mechanism that
operates only on local changes. Modifications/additions coming in via sync
command are not processed by hooks.