Re: memory usage issue for double-float operations

Stas Boukarev <[email protected]> Wed, 16 Oct 2024 19:30:43 +0300
Newsgroups gmane.lisp.steel-bank.general
Message-ID <CAF63=11Q=gTBZ5+P+UeZem41=u0wiV6h07VM-ZbSgu-Eo4hE6w@mail.gmail.com>
Thanks for testing.

On Wed, Oct 16, 2024 at 7:27 PM Matt Kaufmann <[email protected]>
wrote:

> Aha!  Thanks so much -- my actual application (from which that email
> and the two bug reports were distilled) is now performing as hoped.
>
> Gratefully,
> Matt
> Stas Boukarev <[email protected]> writes:
>
> > [1:text/plain Hide]
> >
> > It has to be
> > (declaim (ftype (function (t)
> >                           (values double-float &optional))
> >                 aref0))
> >
> > i.e. a fixed number of return values.
> >
> > On Wed, Oct 16, 2024 at 6:54 PM Matt Kaufmann <[email protected]>
> > wrote:
> >
> >> Hi,
> >>
> >> I appreciate being able to avoid memory usage when passing
> >> double-floats through function calls.  But I'm still running into an
> >> issue with that, even with fixes to recent SBCL bugs 2084209 and
> >> 2084398.  Using SBCL downloaded and built this morning on my Mac (SBCL
> >> 2.4.9.52-28385348a), the simple script below results in memory usage
> >> that surprises me, and shows that this usage disappears with inlining:
> >>
> >> * (load "sbcl-script.lsp")
> >> Bytes used for 10000 iterations of (foo *my-ar*): 163840
> >> Bytes used for 10000 iterations of (foo-inline *my-ar*): 0
> >> T
> >> *
> >>
> >> Am I doing something wrong?
> >>
> >> Thanks,
> >> Matt [script is below]
> >> (defvar *my-ar*
> >>   (make-array 3
> >>               :element-type 'double-float
> >>               :initial-contents '(3.0d0 4.0d0 5.0d0)))
> >>
> >> (declaim (ftype (function (t)
> >>                           double-float) ; or (values double-float)
> >>                 aref0))
> >>
> >> (declaim (inline aref0-inline))
> >>
> >> (defun aref0 (ar)
> >>   (the double-float
> >>        (aref (the (simple-array double-float (*))
> >>                   ar)
> >>              0)))
> >>
> >> (defun aref0-inline (ar)
> >>   (the double-float
> >>        (aref (the (simple-array double-float (*))
> >>                   ar)
> >>              0)))
> >>
> >> (defun foo (ar)
> >>   (= (the double-float
> >>           (* 2.0d0
> >>              (the double-float
> >>                   (aref0 ar))))
> >>      5.0d0))
> >>
> >> (defun foo-inline (ar)
> >>   (= (the double-float
> >>           (* 2.0d0
> >>              (the double-float
> >>                   (aref0-inline ar))))
> >>      5.0d0))
> >>
> >> ; Bytes used = 163840
> >> (let ((start (sb-ext:get-bytes-consed)))
> >>   (loop for i from 1 to 10000 do (foo *my-ar*))
> >>   (format t "Bytes used for 10000 iterations of (foo *my-ar*): ~s~%"
> >>           (- (sb-ext:get-bytes-consed) start)))
> >>
> >> ; Bytes used = 0
> >> (let ((start (sb-ext:get-bytes-consed)))
> >>   (loop for i from 1 to 10000 do (foo-inline *my-ar*))
> >>   (format t "Bytes used for 10000 iterations of (foo-inline *my-ar*):
> ~s"
> >>           (- (sb-ext:get-bytes-consed) start)))
> >>
> >> Stas Boukarev <[email protected]> writes:
> >>
> >> > [1:text/plain Hide]
> >> >
> >> > It could be made to work without any intervention at all, but it's
> >> probably
> >> > not a good idea to automatically generate extra entry points when not
> >> > needed.
> >> > ftype seems reasonable and standard, for now.
> >> >
> >> > On Tue, Oct 8, 2024 at 6:19 PM Michał Herda | Keepit <[email protected]>
> >> wrote:
> >> >
> >> >> Thanks for that optimization. One more question from me: is this
> going
> >> to
> >> >> work automatically with *DERIVE-FUNCTION-TYPES*, or are manual ftype
> >> >> proclamations still necessary in that case?
> >> >> ------------------------------
> >> >> *From:* Stas Boukarev <[email protected]>
> >> >> *Sent:* Tuesday, October 8, 2024 5:17 PM
> >> >> *To:* Matt Kaufmann <[email protected]>
> >> >> *Cc:* [email protected] <[email protected]>;
> >> >> [email protected] <[email protected]>
> >> >> *Subject:* Re: [Sbcl-help] memory usage issue for double-float
> >> operations
> >> >>
> >> >> No block compilation is needed, or any other non-standard feature.
> >> >>
> >> >> On Tue, Oct 8, 2024 at 6:15 PM Matt Kaufmann <[email protected]
> >
> >> >> wrote:
> >> >>
> >> >> Thank you so much; very cool!  Is block compilation necessary for
> this
> >> >> to work?
> >> >>
> >> >> Stas Boukarev <[email protected]> writes:
> >> >>
> >> >> > [1:text/plain Hide]
> >> >> >
> >> >> > Now unboxed returns also work. Trace works as well. The following
> no
> >> >> longer
> >> >> > conses:
> >> >> >
> >> >> > (declaim (type (simple-array double-float (1)) *ar*))
> >> >> >
> >> >> > (defvar *ar* (make-array 1
> >> >> >                          :element-type 'double-float
> >> >> >                          :initial-element 0.0d0))
> >> >> >
> >> >> > (declaim (ftype (function (double-float) (values double-float
> >> &optional))
> >> >> >                 f1))
> >> >> >
> >> >> > (defun f1 (v)
> >> >> >   (+ v v))
> >> >> >
> >> >> > (declaim (ftype (function (double-float) *) f2))
> >> >> >
> >> >> > (defun f2 (v)
> >> >> >   (loop for i from 1 to 1000
> >> >> >         do
> >> >> >         (setf (aref *ar* 0) (f1 v))))
> >> >> >
> >> >> >
> >> >> > On Tue, Oct 8, 2024 at 12:17 AM Stas Boukarev <[email protected]>
> >> >> wrote:
> >> >> >
> >> >> >> I just pushed the initial attempt for unboxed arguments, so the
> >> >> following
> >> >> >> doesn't cons anymore:
> >> >> >>
> >> >> >> (declaim (ftype (function (double-float double-float) (values t
> >> >> >> &optional)) f))
> >> >> >>
> >> >> >> (defun f (a b)
> >> >> >>   (> (+ a b) 3d0))
> >> >> >>
> >> >> >> (defun bar (n)
> >> >> >>   (declare (fixnum n))
> >> >> >>   (f (* pi n) (* pi (1+ n))))
> >> >> >>
> >> >> >>
> >> >> >> Not consing the return value will come in the near future. #'f
> works
> >> as
> >> >> >> expected, and incompatible redefinitions behave reasonably. trace
> >> >> doesn't
> >> >> >> yet work.
> >> >> >>
> >> >> >> On Sun, Sep 29, 2024 at 1:46 AM Stas Boukarev <[email protected]
> >
> >> >> wrote:
> >> >> >>
> >> >> >>> It could be improved in the future, but currently it's really not
> >> ready
> >> >> >>> for public use and may change at any time.
> >> >> >>> You might try block compilation instead.
> >> >> >>>
> >> >> >>> On Sun, Sep 29, 2024 at 1:37 AM Matt Kaufmann <
> >> [email protected]>
> >> >> >>> wrote:
> >> >> >>>
> >> >> >>>> I very much appreciate all the replies, and I think I
> understand.
> >> >> >>>> Thank you, all who replied!
> >> >> >>>>
> >> >> >>>> > > That's not directly supported by SBCL's current calling
> >> >> conventions.
> >> >> >>>> >
> >> >> >>>> > It is actually supported, but we don't advertise it or make it
> >> >> >>>> well-behaved
> >> >> >>>> > when misused.
> >> >> >>>>
> >> >> >>>> In our application we can arrange for every function to have a
> >> >> >>>> suitable ftype proclaimed before it is defined, so that
> >> double-floats
> >> >> >>>> are passed and returned only as indicated by the function's
> ftype;
> >> >> >>>> also, every function is defined before it is called.  If these
> >> suffice
> >> >> >>>> to guarantee no "misuse" of support for avoiding boxing, and if
> >> there
> >> >> >>>> is a reasonably simple way to provide that support (like setting
> >> some
> >> >> >>>> global), then I'd like to know how that can work, provided that
> >> such
> >> >> >>>> support is likely to remain available in SBCL.
> >> >> >>>>
> >> >> >>>> Thanks,
> >> >> >>>> Matt
> >> >> >>>> Stas Boukarev <[email protected]> writes:
> >> >> >>>>
> >> >> >>>> > [1:multipart/alternative Hide]
> >> >> >>>> >
> >> >> >>>> >
> >> >> >>>> > [1/1:text/plain Hide]
> >> >> >>>> >
> >> >> >>>> >> That's not directly supported by SBCL's current calling
> >> >> conventions.
> >> >> >>>> >
> >> >> >>>> > It is actually supported, but we don't advertise it or make it
> >> >> >>>> well-behaved
> >> >> >>>> > when misused.
> >> >> >>>> >
> >> >> >>>> > On Sun, Sep 29, 2024 at 12:30 AM Christophe Rhodes <
> >> >> [email protected]>
> >> >> >>>> wrote:
> >> >> >>>> >
> >> >> >>>> >> Matt Kaufmann <[email protected]> writes:
> >> >> >>>> >>
> >> >> >>>> >> > I'd really like to avoid boxing of double-floats returned
> by
> >> >> >>>> function
> >> >> >>>> >> > calls.
> >> >> >>>> >>
> >> >> >>>> >> Avoiding boxing is, essentially, arranging that there be a
> known
> >> >> >>>> >> location for the callee and the caller to cooperate in
> writing
> >> and
> >> >> >>>> >> reading an unboxed return value, without risking that value
> >> being
> >> >> >>>> >> accidentally interpreted as a tagged lisp object pointer.
> >> >> >>>> >>
> >> >> >>>> >> That's not directly supported by SBCL's current calling
> >> >> conventions.
> >> >> >>>> >> But you can do it yourself: have your function, instead of
> >> >> returning a
> >> >> >>>> >> double-float, take as an argument a (simple-array
> double-float
> >> >> (1)),
> >> >> >>>> and
> >> >> >>>> >> write its result there; the caller can read the value from
> >> there,
> >> >> and
> >> >> >>>> >> all should happen without consing:
> >> >> >>>> >>
> >> >> >>>> >> (defun f1 (v result)
> >> >> >>>> >>   (declare (type double-float v)
> >> >> >>>> >>            (type (simple-array double-float (1)) result))
> >> >> >>>> >>   (setf (aref result 0) (+ v v))
> >> >> >>>> >>   (values))
> >> >> >>>> >>
> >> >> >>>> >> (defvar *ar* (make-array 1 :element-type 'double-float))
> >> >> >>>> >> (declaim (type (simple-array double-float (1)) *ar*))
> >> >> >>>> >>
> >> >> >>>> >> (defun f2 (v)
> >> >> >>>> >>   (let ((f1r (make-array 1 :element-type 'double-float)))
> >> >> >>>> >>     (declare (dynamic-extent f1r))
> >> >> >>>> >>     (loop repeat 1000
> >> >> >>>> >>           do (setf (aref *ar* 0) (progn (f1 v f1r) (aref f1r
> >> >> 0))))))
> >> >> >>>> >>
> >> >> >>>> >> Christophe
> >> >> >>>> >>
> >> >> >>>> >> > Below is a small example that boxes unless the function is
> >> >> >>>> >> > made inline.  Is there, or could there be, a way to avoid
> >> boxing
> >> >> the
> >> >> >>>> >> > double-float result, other than inlining?  Or should I just
> >> >> accept
> >> >> >>>> >> > that this is somehow not possible?  (Thanks again, Michał
> >> "phoe"
> >> >> >>>> >> > Herda, for the reply; note that I've done all I could
> below to
> >> >> avoid
> >> >> >>>> >> > boxing inputs.)
> >> >> >>>> >> >
> >> >> >>>> >> > (declaim (optimize (compilation-speed 0) (debug 0) (speed
> 3)
> >> >> (space
> >> >> >>>> 0)
> >> >> >>>> >> >                    (safety 0)))
> >> >> >>>> >> >
> >> >> >>>> >> > (declaim (type (simple-array double-float (1)) *ar*))
> >> >> >>>> >> >
> >> >> >>>> >> > (defvar *ar* (make-array '(1)
> >> >> >>>> >> >                          :element-type 'double-float
> >> >> >>>> >> >                          :initial-element 0.0d0))
> >> >> >>>> >> >
> >> >> >>>> >> > (declaim (ftype (function (double-float) double-float)
> >> >> >>>> >> >                 f1))
> >> >> >>>> >> >
> >> >> >>>> >> > ; (declaim (inline f1)) ; eliminates consing for (time (f2
> >> >> 1.0d0))
> >> >> >>>> below
> >> >> >>>> >> >
> >> >> >>>> >> > (defun f1 (v)
> >> >> >>>> >> >   (declare (type double-float v))
> >> >> >>>> >> >   (the double-float (+ v v)))
> >> >> >>>> >> >
> >> >> >>>> >> > (declaim (ftype (function (double-float) *)
> >> >> >>>> >> >                 f2))
> >> >> >>>> >> >
> >> >> >>>> >> > (defun f2 (v)
> >> >> >>>> >> >   (declare (type double-float v))
> >> >> >>>> >> >   (loop for i from 1 to 1000
> >> >> >>>> >> >         do
> >> >> >>>> >> >         (setf (aref (the (simple-array double-float (1))
> >> >> >>>> >> >                          *ar*)
> >> >> >>>> >> >                     0)
> >> >> >>>> >> >               (the double-float (f1 v)))))
> >> >> >>>> >> >
> >> >> >>>> >> > ; 32,768 bytes consed, except 0 if f1 calls are inlined:
> >> >> >>>> >> > (time (f2 1.0d0))
> >> >> >>>> >> >
> >> >> >>>> >> > Matt Kaufmann <[email protected]> writes:
> >> >> >>>> >> >
> >> >> >>>> >> >> Very interesting.  I expected the declare form in the
> defun
> >> of
> >> >> >>>> >> >> my-update --
> >> >> >>>> >> >>
> >> >> >>>> >> >>     (declare (type (simple-array double-float (*)) ar)
> >> >> >>>> >> >>              (type double-float v))
> >> >> >>>> >> >>
> >> >> >>>> >> >> -- to avoid boxing.  As another experiment I added the
> >> following
> >> >> >>>> just
> >> >> >>>> >> >> before the defun of my-update -- but consing still
> occurred.
> >> >> >>>> >> >>
> >> >> >>>> >> >> (declaim (ftype (function ((simple-array double-float
> (*)) t
> >> >> >>>> >> double-float)
> >> >> >>>> >> >>                           double-float)
> >> >> >>>> >> >>                 my-update))
> >> >> >>>> >> >>
> >> >> >>>> >> >> Apparently those extra efforts don't change your point
> about
> >> >> >>>> boxing,
> >> >> >>>> >> >> which contradicts what I thought I understood.  I
> appreciate
> >> the
> >> >> >>>> help!
> >> >> >>>> >> >>
> >> >> >>>> >> >> Thanks,
> >> >> >>>> >> >> Matt
> >> >> >>>> >> >> Michał "phoe" Herda <[email protected]> writes:
> >> >> >>>> >> >>
> >> >> >>>> >> >>> Converting a double float to a function argument requires
> >> >> boxing,
> >> >> >>>> which
> >> >> >>>> >> >>> allocates memory. If the function is inlined, there are
> no
> >> >> >>>> arguments to
> >> >> >>>> >> >>> pass, so there can be no consing.
> >> >> >>>> >> >>>
> >> >> >>>> >> >>> On 26.09.2024 01:55, Matt Kaufmann wrote:
> >> >> >>>> >> >>>> Thanks so much!
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> I see that suitable THE declarations also avoid consing.
> >> But
> >> >> >>>> >> >>>> inserting a function call can cause consing, whether
> using
> >> THE
> >> >> >>>> or your
> >> >> >>>> >> >>>> declaim form, as illustrated below.  I'd be interested
> in
> >> any
> >> >> >>>> insights
> >> >> >>>> >> >>>> about why that function call causes consing.
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> (declaim (optimize (compilation-speed 0) (debug 0)
> (speed
> >> 3)
> >> >> >>>> (space 0)
> >> >> >>>> >> >>>>                     (safety 0)))
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> ; Optional:
> >> >> >>>> >> >>>> ; (declaim (type (simple-array double-float (5000))
> *ar*))
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> (defvar *ar* (make-array '(5000)
> >> >> >>>> >> >>>>                           :element-type 'double-float
> >> >> >>>> >> >>>>                           :initial-element 0.0d0))
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> (loop with i of-type (integer 0 *) = 0 do
> >> >> >>>> >> >>>>        (cond ((>= i 5000)
> >> >> >>>> >> >>>>               (return))
> >> >> >>>> >> >>>>              (t (progn (setf (aref *ar* i)
> >> >> >>>> >> >>>>                              (float i 0.0d0))
> >> >> >>>> >> >>>>                        (setq i (1+ i))))))
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> (defun foo (ar)
> >> >> >>>> >> >>>>    (loop with i = 0 do
> >> >> >>>> >> >>>>          (cond
> >> >> >>>> >> >>>>           ((>= i 4999) ; <-- for i from 0 to 4999 ...
> >> >> >>>> >> >>>>            (return))
> >> >> >>>> >> >>>>           (t (setf (aref (the (simple-array double-float
> >> (*))
> >> >> ar)
> >> >> >>>> >> >>>>                          i)
> >> >> >>>> >> >>>>                    (the double-float
> >> >> >>>> >> >>>>                         (+ 1.0d0
> >> >> >>>> >> >>>>                            (the double-float
> >> >> >>>> >> >>>>                                 (aref (the (simple-array
> >> >> >>>> double-float
> >> >> >>>> >> *) ar)
> >> >> >>>> >> >>>>                                       i)))))
> >> >> >>>> >> >>>>              (setq i (1+ i))))))
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> (time (foo *ar*)) ; 0 bytes consed
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> ; Optional:
> >> >> >>>> >> >>>> (declaim (inline my-update))
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> (defun my-update (ar i v)
> >> >> >>>> >> >>>>    (declare (type (simple-array double-float (*)) ar)
> >> >> >>>> >> >>>>             (type double-float v))
> >> >> >>>> >> >>>>    (setf (aref (the (simple-array double-float (*)) ar)
> >> >> >>>> >> >>>>                i)
> >> >> >>>> >> >>>>          v))
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> (defun foo2 (ar)
> >> >> >>>> >> >>>>    (loop with i = 0 do
> >> >> >>>> >> >>>>          (cond
> >> >> >>>> >> >>>>           ((>= i 4999) ; <-- for i from 0 to 4999 ...
> >> >> >>>> >> >>>>            (return))
> >> >> >>>> >> >>>>           (t (my-update ar
> >> >> >>>> >> >>>>                         i
> >> >> >>>> >> >>>>                         (the double-float
> >> >> >>>> >> >>>>                              (+ 1.0d0
> >> >> >>>> >> >>>>                                 (the double-float
> >> >> >>>> >> >>>>                                      (aref (the
> >> (simple-array
> >> >> >>>> >> double-float *)
> >> >> >>>> >> >>>>                                                 ar)
> >> >> >>>> >> >>>>                                            i)))))
> >> >> >>>> >> >>>>              (setq i (1+ i))))))
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> (time (foo2 *ar*)) ; 65,536 bytes consed if not
> inlined, 0
> >> >> >>>> otherwise
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>> Thanks,
> >> >> >>>> >> >>>> Matt
> >> >> >>>> >> >>>> Michał "phoe" Herda <[email protected]> writes:
> >> >> >>>> >> >>>>
> >> >> >>>> >> >>>>> (declaim (type (simple-array double-float (5000))
> *ar*))
> >> >> >>>> >> >>>>>
> >> >> >>>> >> >>>>> On 25.09.2024 21:44, Matt Kaufmann wrote:
> >> >> >>>> >> >>>>>> Hi,
> >> >> >>>> >> >>>>>>
> >> >> >>>> >> >>>>>> Is there a way to modify the example below so that the
> >> final
> >> >> >>>> form
> >> >> >>>> >> does
> >> >> >>>> >> >>>>>> not allocate memory in SBCL?  (To be fair, I tried
> >> several
> >> >> >>>> other
> >> >> >>>> >> Lisps
> >> >> >>>> >> >>>>>> as well, and all of them allocated memory.)
> >> >> >>>> >> >>>>>>
> >> >> >>>> >> >>>>>> (declaim (optimize (compilation-speed 0) (debug 0)
> >> (speed 3)
> >> >> >>>> (space
> >> >> >>>> >> 0)
> >> >> >>>> >> >>>>>>                      (safety 0)))
> >> >> >>>> >> >>>>>>
> >> >> >>>> >> >>>>>> (defvar *ar* (make-array '(5000)
> >> >> >>>> >> >>>>>>                            :element-type 'double-float
> >> >> >>>> >> >>>>>>                            :initial-element 0.0d0))
> >> >> >>>> >> >>>>>>
> >> >> >>>> >> >>>>>> (loop with i of-type (integer 0 *) = 0 do
> >> >> >>>> >> >>>>>>         (cond ((>= i 5000)
> >> >> >>>> >> >>>>>>                (return))
> >> >> >>>> >> >>>>>>               (t (progn (setf (aref *ar* i)
> >> >> >>>> >> >>>>>>                               (float i 0.0d0))
> >> >> >>>> >> >>>>>>                         (setq i (1+ i))))))
> >> >> >>>> >> >>>>>>
> >> >> >>>> >> >>>>>> (defun foo ()
> >> >> >>>> >> >>>>>>     (loop with i of-type fixnum = 0 do
> >> >> >>>> >> >>>>>>           (cond
> >> >> >>>> >> >>>>>>            ((>= i 4999) ; <-- for i from 0 to 4999 ...
> >> >> >>>> >> >>>>>>             (return))
> >> >> >>>> >> >>>>>>            (t (setf (aref *ar* i)
> >> >> >>>> >> >>>>>>                     (the double-float
> >> >> >>>> >> >>>>>>                          (+ 1.0d0
> >> >> >>>> >> >>>>>>                             (the double-float (aref
> *ar*
> >> >> i)))))
> >> >> >>>> >> >>>>>>               (setq i (the fixnum (1+ i)))))))
> >> >> >>>> >> >>>>>>
> >> >> >>>> >> >>>>>> (time (foo))
> >> >> >>>> >> >>>>>>
> >> >> >>>> >> >>>>>> Thanks,
> >> >> >>>> >> >>>>>> Matt
> >> >> >>>> >> >>>>>>
> >> >> >>>> >> >>>>>>
> >> >> >>>> >> >>>>>> _______________________________________________
> >> >> >>>> >> >>>>>> Sbcl-help mailing list
> >> >> >>>> >> >>>>>> [email protected]
> >> >> >>>> >> >>>>>>
> https://lists.sourceforge.net/lists/listinfo/sbcl-help
> >> >> >>>> >> >>
> >> >> >>>> >> >>
> >> >> >>>> >> >> _______________________________________________
> >> >> >>>> >> >> Sbcl-help mailing list
> >> >> >>>> >> >> [email protected]
> >> >> >>>> >> >> https://lists.sourceforge.net/lists/listinfo/sbcl-help
> >> >> >>>> >> >
> >> >> >>>> >> >
> >> >> >>>> >> > _______________________________________________
> >> >> >>>> >> > Sbcl-help mailing list
> >> >> >>>> >> > [email protected]
> >> >> >>>> >> > https://lists.sourceforge.net/lists/listinfo/sbcl-help
> >> >> >>>> >>
> >> >> >>>> >>
> >> >> >>>> >> _______________________________________________
> >> >> >>>> >> Sbcl-help mailing list
> >> >> >>>> >> [email protected]
> >> >> >>>> >> https://lists.sourceforge.net/lists/listinfo/sbcl-help
> >> >> >>>> >>
> >> >> >>>> >
> >> >> >>>> > [1/2:text/html Show Save:noname (38kB)]
> >> >> >>>> >
> >> >> >>>> >
> >> >> >>>> > [2:text/plain Hide]
> >> >> >>>> >
> >> >> >>>> >
> >> >> >>>> > [3:text/plain Hide]
> >> >> >>>> >
> >> >> >>>> > _______________________________________________
> >> >> >>>> > Sbcl-help mailing list
> >> >> >>>> > [email protected]
> >> >> >>>> > https://lists.sourceforge.net/lists/listinfo/sbcl-help
> >> >> >>>>
> >> >> >>>>
> >> >> >>>> _______________________________________________
> >> >> >>>> Sbcl-help mailing list
> >> >> >>>> [email protected]
> >> >> >>>> https://lists.sourceforge.net/lists/listinfo/sbcl-help
> >> >> >>>>
> >> >> >>>
> >> >> >
> >> >> > [2:text/html Show Save:noname (54kB)]
> >> >>
> >> >>
> >> >>
> >> >>
> >> >> This e-mail is sent to you from Keepit A/S. Dedicated SaaS Data
> >> Protection.
> >> >> VAT: DK30806883, Per Henrik Lings Allé 4, 7., DK-2100 Copenhagen Ø,
> >> >> Denmark.
> >> >>
> >> >> This e-mail is sent to you directly and is meant for nobody else. If
> the
> >> >> e-mail contains personal data that Keepit is responsible for and the
> >> e-mail
> >> >> was not meant for you, please do not forward, distribute, or copy,
> i.e.
> >> but
> >> >> return the e-mail to sender. Also, do not send the e-mail to a third
> >> party
> >> >> without making sure that you have our prior consent. Distribution of
> >> this
> >> >> e-mail to unauthorized receivers may have legal consequences.
> >> >> If you have received an e-mail from us and you don’t know why, then
> >> please
> >> >> refer to our Privacy Policy <https://www.keepit.com/privacy-policy/
> >.
> >> >> If you do not want to receive more e-mails from us, please contact
> >> >> [email protected].
> >> >>
> >> >
> >> > [2:text/html Show Save:noname (75kB)]
> >>
> >
> > [2:text/html Show Save:noname (91kB)]
>

_______________________________________________
Sbcl-help mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/sbcl-help