wanted: efficient out-of-line structure slot setters

Bug #309463 reported by Nikodemus Siivola
2
Affects Status Importance Assigned to Milestone
SBCL
Fix Released
Wishlist
Unassigned

Bug Description

  In sbcl-0.6.11.41 (and in all earlier SBCL, and in CMU
  CL), out-of-line structure slot setters are horribly inefficient
  whenever the type of the slot is declared, because out-of-line
  structure slot setters are implemented as closures to save space,
  so the compiler doesn't compile the type test into code, but
  instead just saves the type in a lexical closure and interprets it
  at runtime.
    To exercise the problem, compile and load
      (cl:in-package :cl-user)
      (defstruct foo
        (bar (error "missing") :type bar))
      (defvar *foo*)
      (defun wastrel1 (x)
        (loop (setf (foo-bar *foo*) x)))
      (defstruct bar)
      (defvar *bar* (make-bar))
      (defvar *foo* (make-foo :bar *bar*))
      (defvar *setf-foo-bar* #'(setf foo-bar))
      (defun wastrel2 (x)
        (loop (funcall *setf-foo-bar* x *foo*)))
  then run (WASTREL1 *BAR*) or (WASTREL2 *BAR*), hit Ctrl-C, and
  use BACKTRACE, to see it's spending all essentially all its time
  in %TYPEP and VALUES-SPECIFIER-TYPE and so forth.
    One possible solution would be simply to give up on
  representing structure slot accessors as functions, and represent
  them as macroexpansions instead. This can be inconvenient for users,
  but it's not clear that it's worse than trying to help by expanding
  into a horribly inefficient implementation.
    As a workaround for the problem, #'(SETF FOO) expressions
  can be replaced with (EFFICIENT-SETF-FUNCTION FOO), where
(defmacro efficient-setf-function (place-function-name)
  (or #+sbcl (and (sb-int:info :function :accessor-for place-function-name)
    ;; a workaround for the problem, encouraging the
    ;; inline expansion of the structure accessor, so
    ;; that the compiler can optimize its type test
    (let ((new-value (gensym "NEW-VALUE-"))
                        (structure-value (gensym "STRUCTURE-VALUE-")))
      `(lambda (,new-value ,structure-value)
         (setf (,place-function-name ,structure-value)
        ,new-value))))
      ;; no problem, can just use the ordinary expansion
      `(function (setf ,place-function-name))))

Changed in sbcl:
importance: Undecided → Low
status: New → Confirmed
tags: added: optimization
summary: - inefficient out-of-line structure slot setters
+ wanted: efficient out-of-line structure slot setters
Changed in sbcl:
importance: Low → Wishlist
Revision history for this message
Stas Boukarev (stassats) wrote :

In 02fa22e7c496fb6aefa0a83c86dcdd302d27fb4a.

Changed in sbcl:
status: Confirmed → Fix Committed
Stas Boukarev (stassats)
Changed in sbcl:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.