I have sketched an implementation of special variables that works _mostly_ like SBCL's. The idea is that each symbol which is dynamically bound is assigned an index. This index is used to look up in a thread-local storage that contains the actual values of the symbol.<br>
<br>The difference between SBCL's implementation and what I have done are<br>- Right now the sketch is not inlined -- requires a function call per lookup<br>- The storage region may grow and need not have the same size for each thread<br>
- Indices into the table are reused when symbols are garbage collected.<br><br>Results are encouraging. For a simple test program shown below the old implementation gives<br><br>FOO<br>real time : 0.817 secs<br>run time : 0.817 secs<br>
gc count : 1 times<br>consed : 0 bytes<br>BASE<br>real time : 0.203 secs<br>run time : 0.203 secs<br>gc count : 1 times<br>consed : 0 bytes<br><br>Once we subtract the cost of calling BASE with the improvements of hash tables this gives 617 ms for 1e7 lookups and bindings.<br>
<br>The new scheme OTOH<br><br>FOO<br>real time : 0.301 secs<br>run time : 0.300 secs<br>gc count : 1 times<br>consed : 0 bytes<br>BASE<br>real time : 0.203 secs<br>run time : 0.203 secs<br>gc count : 1 times<br>consed : 0 bytes<br>
<br>that is 100 ms, or 1/6th.<br><br>(require 'cmp)<br>(proclaim '(optimize (speed 3) (safety 0)))<br>(defvar *a* 3)<br>(compile 'faa '(lambda (x) x))<br>(compile 'foo '(lambda (x)<br> (dotimes (i 10000000)<br>
(declare (fixnum i))<br> (let ((*a* x)) (faa *a*)))))<br>(compile 'base '(lambda (x)<br> (dotimes (i 10000000)<br> (declare (fixnum i))<br> (faa x))))<br>(ext:gc t)<br>
(princ 'FOO)<br>(time (foo 1))<br>(time (foo 1))<br>(princ 'BASE)<br>(time (base 2))<br>(time (base 2))<br><br clear="all"><br>-- <br>Instituto de Física Fundamental, CSIC<br>c/ Serrano, 113b, Madrid 28006 (Spain) <br>
<a href="http://juanjose.garciaripoll.googlepages.com">http://juanjose.garciaripoll.googlepages.com</a><br>