I thought I'd report back briefly on some results.
First, I spent some time attempting to implement "perform with session state". This is the idea that when working with ASDF, it would be useful to be able to invoke or create specific behavior for my use case and also to be able to capture work session state without relying on globals. This was partially successful, but I broke something and ran out of patience. ASDF is some wonderful code, but takes a bit to grok it all.
So I took the crude approach of just installing a global and using it to accumulate loaded files from within a perform. I created an .asd file which defined the dependencies I wanted the image to have. The loaded it with load-system. Then at the end of load-system I inserted code to save a structure containing a list of the *defined-systems* as well as a list of the loaded files (in order of loading).
The next step was to create a little loader script which loads all of the files, and then populates *modules* via satisfies. There were a couple of glitches. For one, a couple of systems had hard coded asdf dependencies. After removing them, they compiled fine. Then another system required asdf-system-connections. I needed to remove that out of the file load list because it isn't necessary after things are loaded.
Finally the load list works, the image saves and starts just fine. I can use regular ol' REQUIRE to provide a sanity check, although I realize this may not be the best approach, at least it works without extra code.
This saved about 10% on the image size compared to asdf-loading the same systems, and cleared out some unnecessary dependencies. It will take a while to work out the best "batteries included" image. I can always load ASDF for a given project if it needs to incorporate other systems, smaller projects can just load themselves.
Of course for development I'll still be using ASDF a hundred times a day!
Erik.
On Mon, Apr 23, 2012 at 2:10 PM, Robert Goldman rpgoldman@sift.info wrote:
On 4/23/12 Apr 23 -3:52 PM, Erik Pearson wrote:
Hi Robert, What I was thinking is that OPERATE assembles the plan via TRAVERSE, then executes it via PERFORM-PLAN, which calls PERFORM to translate the abstraction of operation + component into an action with side effect. It seems to me that it is each PERFORM (or, rather, the ones that we are interested in) that needs to be captured, since it is only in the body of the PERFORM method that the abstractions are made concrete in into lisp forms which carry out the desired actions.
What I am referring to as "recording" is to append the lisp forms produced by each PERFORM into a list or other structure. At present this structure would need to be a global, but ideally it would be a slot in a session object that threads through each PERFORM. It is because the PERFORMS are carried out serially by PERFORM-PLAN according to the plan assembled by TRAVERSE that they can be "played back" to recreate the actions of this asdf session. Now if there were parallel executions of PERFORMs by PERFORM-PLAN, that would be different...
I hope that makes sense.
I suppose, but I don't know how you break into what PERFORM does.
A quick and dirty way, as I described above, does require breaking into PERFORM. But I think you could either create an alternate method and inject that at around the PERFORM-PLAN level, or use a SESSION object as an additional specializer argument to open up other possible PERFORM implementations.
I was thinking you would precompute and cache the plan, and then invoke PERFORM-PLAN on that.
Or maybe another method altogether to take the place of perform, like SIMULATE-PLAN or RECORD-PLAN, or ASSEMBLE-PLAN.
That assumes that the call to TRAVERSE is actually expensive enough that this is worth the trouble. I think you could confirm or disconfirm that claim quickly with some timing experiments.
Yes, I think I did that -- but with a different concern. When I was concerned about ASDF mucking around inspecting files when I was doing a REQUIRE, I added a feature to cause a fully loaded module to be flagged as loaded via mark-operation-done, so that do-traverse would stop traversing at such a module. It was about 2.5 seconds to traverse normally, and about 0.5 with this optimization for a require after the first one (of course for a deployed system not development.)
In any case load time is not my only interest. It is also a desire to be able to use ASDF more effectively for more use cases.
Erik.
cheers,
r