* The most expensive operation was the cost of a missing
Code.ensure_loaded?/1 call, since it performs a file system
traversal. For this reason the new implementation simply
assumes the module has been loaded, because we tried to run
its tests, otherwise we don't assume anything at all. This
was particurlaly expensive when running only a subset of the
suite. This change reduced the time from 3.3s to 120ms.
* The second most expensive operation was the conversions from
map to list and vice-versa. Adding tests in a loop also caused
frequent updates in the map. To solve this, we store the manifest
as a list, simply prepending entries which is very cheap, and
convert only the new manifest to a map and only once. The prune
and merging steps have been unified, reducing the time to 0.6ms.
* A `new` function has also been added so we can create manifest
in other files without hardcoding its internal structure. The
manifest type has been declare as opaque.