This patch accelerates work with array
*** c:\temp\uffi-compat.lisp Wed Nov 9 21:23:12 2005 --- c:\temp\cffi-luis-051114-1956\uffi-compat\uffi-compat.lisp Fri Dec 16 13:53:55 2005 *************** *** 131,137 **** (:documentation "UFFI's :array type."))
(defmethod initialize-instance :after ((self uffi-array-type) &key) ! (setf (cffi::actual-type self) (cffi::find-type :pointer)))
(defmethod cffi:foreign-type-size ((type uffi-array-type)) (or (* (cffi:foreign-type-size (element-type type)) (nelems type)) --- 131,144 ---- (:documentation "UFFI's :array type."))
(defmethod initialize-instance :after ((self uffi-array-type) &key) ! (setf (cffi::actual-type self) (cffi::find-type :pointer)) ! (setf (cffi::name self) ! (intern (format nil "~A-~A-~A-~D" ! (cffi::symbol-name '#:anon) ! (cffi::class-name (class-of self)) ! (element-type self) ! (nelems self)))) ! )
(defmethod cffi:foreign-type-size ((type uffi-array-type)) (or (* (cffi:foreign-type-size (element-type type)) (nelems type)) *************** *** 141,148 **** t)
(cffi:define-type-spec-parser uffi-array (element-type count) ! (make-instance 'uffi-array-type :element-type element-type :nelems count)) ! ;; UFFI's :(unsigned-)char (cffi:define-foreign-type uffi-char (base-type) base-type) --- 148,158 ---- t)
(cffi:define-type-spec-parser uffi-array (element-type count) ! (cond ((cffi::find-type (intern (format nil "ANON-UFFI-ARRAY-TYPE-~A-~D" ! element-type ! count)))) ! (t (make-instance 'uffi-array-type :element-type element-type :nelems count)))) ! ;; UFFI's :(unsigned-)char (cffi:define-foreign-type uffi-char (base-type) base-type)
Леонид Новиков ln@bk.ru writes:
This patch accelerates work with array
Hi, I suspect the following patch will be even faster (though I don't have any numbers, do you?). Do let me know if it works for you.
diff -rN -u cffi-luis-old/uffi-compat/uffi-compat.lisp cffi-luis-new/uffi-compat/uffi-compat.lisp --- cffi-luis-old/uffi-compat/uffi-compat.lisp 2005-12-14 11:02:44.000000000 +0000 +++ cffi-luis-new/uffi-compat/uffi-compat.lisp 2005-12-21 12:00:02.000000000 +0000 @@ -236,9 +236,12 @@
(defmacro deref-array (array type position) "Dereference an array." - `(cffi:mem-aref ,array (element-type - (cffi::parse-type - (convert-uffi-type ,type))) + `(cffi:mem-aref ,array + ,(if (constantp type) + `',(element-type (cffi::parse-type + (convert-uffi-type (eval type)))) + `(element-type (cffi::parse-type + (convert-uffi-type ,type)))) ,position))
;; UFFI's documentation on DEF-UNION is a bit scarce, I'm not sure
Luís Oliveira wrote:
Леонид Новиков ln@bk.ru writes:
This patch accelerates work with array
Hi, I suspect the following patch will be even faster (though I don't have any numbers, do you?). Do let me know if it works for you.
diff -rN -u cffi-luis-old/uffi-compat/uffi-compat.lisp cffi-luis-new/uffi-compat/uffi-compat.lisp --- cffi-luis-old/uffi-compat/uffi-compat.lisp 2005-12-14 11:02:44.000000000 +0000 +++ cffi-luis-new/uffi-compat/uffi-compat.lisp 2005-12-21 12:00:02.000000000 +0000 @@ -236,9 +236,12 @@
(defmacro deref-array (array type position) "Dereference an array."
- `(cffi:mem-aref ,array (element-type
(cffi::parse-type
(convert-uffi-type ,type)))
- `(cffi:mem-aref ,array
,(if (constantp type)
`',(element-type (cffi::parse-type
(convert-uffi-type (eval type))))
`(element-type (cffi::parse-type
(convert-uffi-type ,type)))) ,position))
;; UFFI's documentation on DEF-UNION is a bit scarce, I'm not sure
Yes really this works well. However this will not help for instance in such event: (defun any-func () (let ((ptr (uffi:allocate-foreign-object '(:array :int 10)))) ; some actions are produced with ptr (uffi:free-foreign-object ptr)) ) Object uffi-array-type will create On each call of this functions. If for time of the functioning the program such call several thousand that computer memory ends. My patch allows to avoid this. Its main idea in that arrays with element one and same type and alike length has same type. IMHO this it is correct
Novikov Leonid ln@bk.ru writes:
Yes really this works well. However this will not help for instance in such event: (defun any-func () (let ((ptr (uffi:allocate-foreign-object '(:array :int 10)))) ; some actions are produced with ptr (uffi:free-foreign-object ptr)) )
Ok, one more patch:
diff -rN -u cffi-old/uffi-compat/uffi-compat.lisp cffi-new/uffi-compat/uffi-compat.lisp --- cffi-old/uffi-compat/uffi-compat.lisp 2005-12-21 12:00:02.000000000 +0000 +++ cffi-new/uffi-compat/uffi-compat.lisp 2005-12-26 12:59:25.000000000 +0000 @@ -255,7 +255,10 @@ (defmacro allocate-foreign-object (type &optional (size 1)) "Allocate one or more instance of a foreign type." - `(cffi:foreign-alloc (convert-uffi-type ,type) :count ,size)) + `(cffi:foreign-alloc ,(if (constantp type) + `',(convert-uffi-type (eval type)) + `(convert-uffi-type ,type)) + :count ,size)) (defmacro free-foreign-object (ptr) "Free a foreign object allocated by ALLOCATE-FOREIGN-OBJECT."
So, with this patch you get:
UFFI> (macroexpand-1 '(allocate-foreign-object '(:array :int 10))) (CFFI:FOREIGN-ALLOC '(UFFI-ARRAY :INT 10) :COUNT 1)
This foreign-alloc call will then be optimized by the (yet to be written) compiler macro on foreign-alloc which will calculate the size beforehand when TYPE and COUNT are constant.
Object uffi-array-type will create On each call of this functions. If for time of the functioning the program such call several thousand that computer memory ends.
Well, since those instances of foreign-type won't be needed anymore, they should be garbage collected. They only reason they aren't is because I was saving them in the *foreign-types* hashtable for lame reasons that no longer exist, so this patch will fix that:
diff -rN -u cffi-old/src/early-types.lisp cffi-new/src/early-types.lisp --- cffi-old/src/early-types.lisp 2005-12-11 04:54:41.000000000 +0000 +++ cffi-new/src/early-types.lisp 2005-12-26 13:35:50.000000000 +0000 @@ -92,9 +92,7 @@ (let* ((type-spec (mklist type-spec-or-name)) (parser (find-type-parser (car type-spec)))) (if parser - (let ((new-type (apply parser (cdr type-spec)))) - (notice-foreign-type new-type) - new-type) + (apply parser (cdr type-spec)) (error "Unknown CFFI type: ~S." type-spec-or-name))))) ;;;# Generic Functions on Types
Many thanks for pointing these issues out. Also, I'll keep in mind your patch if the need for a general way to cache types arises.