Whacking down memory usage of CLSQL-SYS::MAP-QUERY-FOR-EFFECT
Kevin Rosenberg <kevin-HJRc7zDS/[email protected]> Sat, 10 Jul 2010 15:53:52 -0600
| Newsgroups | gmane.lisp.clsql.general |
|---|---|
| Message-ID | <[email protected]> |
> Interesting hack. The memory savings is nice. > > It seems like a better place to optimize is in database-store-next-row > from sql/generic-odbc.lisp. The LIST parameter in that function can > then be passed to fetch-row-fn as a new parameter. When that parameter > is non-nil, then fetch-row-fn can store the columns in that parameter > rather than consing a new list. > > Kevin > > On Jul 10, 2010, at 12:52 PM, Jason H wrote: > >> Hi, >> >> A few days ago, I posted a message about CLSQL:MAP-QUERY using more memory >> than CLSQL:QUERY. After poking around a bit deeper in the source code, >> I came up with a hack to greatly reduce the amount of memory used by >> (CLSQL:MAP-QUERY NIL ...). With this hack, the profile report of the >> following 2 test functions: >> >> (defun test-1 () >> (clsql:map-query nil >> #'identity >> (clsql:query "select c1, c2, c3, c4, c5, c6, c7 from Cells"))) >> >> (defun test-2 () >> (clsql:query "select c1, c2, c3, c4, c5, c6, c7 from Cells") ) >> >> is >> >> seconds | consed | calls | sec/call | name >> --------------------------------------------------------- >> 46.778 | 147,860,728 | 1 | 46.777996 | TEST-2 >> 44.614 | 14,768,136 | 1 | 44.613995 | TEST-1 >> >> >> The old profile report without this hack was: >> >> seconds | consed | calls | sec/call | name >> --------------------------------------------------------- >> 46.957 | 147,875,120 | 1 | 46.957000 | TEST-2 >> 44.244 | 161,921,920 | 1 | 44.244000 | TEST-1 >> >> >> The profiling runs were done with the win32 version of sbcl 1.0.37.12. >> The hack is attached at the end of this email and is for the ODBC back-end >> of clsql-5.0.2. >> >> Best, >> >> Jason >> >> ;;------------------------------------------------------------------------------------------------------------- >> >> (in-package :clsql-sys) >> >> ;; new hack >> (defvar *map-query-for-effect-row*) >> >> ;; replace the old MAP-QUERY-FOR-EFFECT. >> (defun map-query-for-effect (function query-expression database result-types) >> (multiple-value-bind (result-set columns) >> (database-query-result-set query-expression database :full-set nil >> :result-types result-types) >> (let ((flatp (and (= columns 1) >> (typep query-expression 'sql-query) >> (slot-value query-expression 'flatp)))) >> (when result-set >> (unwind-protect >> (let ((*map-query-for-effect-row* (make-list columns))) >> (do ((row (make-list columns))) >> ((not (database-store-next-row result-set database row)) >> nil) >> (if flatp >> (apply function row) >> (funcall function row)))) >> (database-dump-result-set result-set database)))))) >> >> (in-package :odbc-dbi) >> >> ;; new hack adapted from DB-FETCH-QUERY-RESULTS. >> (defun db-fetch-single-row (query) >> (declare (type odbc-query query) >> (special clsql-sys::*map-query-for-effect-row*)) >> (when (query-active-p query) >> (with-slots (column-data-ptrs column-c-types column-sql-types >> column-out-len-ptrs column-precisions hstmt >> computed-result-types) >> query >> (let ((cols-fetched 0)) >> (unless (= (%sql-fetch hstmt) odbc::$SQL_NO_DATA_FOUND) >> (loop for result-type across computed-result-types >> for data-ptr across column-data-ptrs >> for c-type across column-c-types >> for sql-type across column-sql-types >> for out-len-ptr across column-out-len-ptrs >> for precision across column-precisions >> for j from 0 ; column count is zero based in lisp >> for rest on clsql-sys::*map-query-for-effect-row* >> do >> (setf (car rest) >> (cond ((< 0 precision (query-width query)) >> (read-data data-ptr c-type sql-type out-len-ptr result-type)) >> ((zerop (get-cast-long out-len-ptr)) >> nil) >> (t >> (read-data-in-chunks hstmt j data-ptr c-type sql-type >> out-len-ptr result-type)))) >> (incf cols-fetched))) >> (values clsql-sys::*map-query-for-effect-row* query cols-fetched))))) >> >> ;; replace the old FETCH-ROW. >> (defun fetch-row (query &optional (eof-errorp t) eof-value) >> (multiple-value-bind (row query count) (db-fetch-single-row query) >> (cond >> ((zerop count) >> (close-query query) >> (when eof-errorp >> (error 'clsql:sql-database-data-error >> :message "ODBC: Ran out of data in fetch-row")) >> eof-value) >> (t >> row)))) >> _______________________________________________ >> CLSQL mailing list >> [email protected] >> http://lists.b9.com/cgi-bin/mailman/listinfo/clsql >> >