Discussion:
References for how declares affect the compiler?
Mark Green
2014-05-22 00:36:27 UTC
Permalink
Hi,

Is there a precise references for what combinations of declares/the's/etc.
actually achieve improvements in the LW compiler and what improvements they
achieve? The reference manual page on declare mentions that declaring types
"removes type checking", what effects do other declarations have?

Mark
Pascal Costanza
2014-05-22 05:35:30 UTC
Permalink
http://www.lispworks.com/documentation/lw61/LW/html/lw-105.htm

Especially http://www.lispworks.com/documentation/lw61/LW/html/lw-110.htm

Pascal

Sent from my iPad
Hi,
Is there a precise references for what combinations of declares/the's/etc. actually achieve improvements in the LW compiler and what improvements they achieve? The reference manual page on declare mentions that declaring types "removes type checking", what effects do other declarations have?
Mark
_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Denis Pousseur
2014-05-22 10:01:25 UTC
Permalink
Dear list,

I just spent several month to optimize some modules of my application. I would like to add some comments about this interesting experience. Thanks for any comment or corrections because I have always a lot of things to learn from you.

Before this experience, I really never understand nothing about this question of optimization because, when I test it, (speed 3) generally doesn’t offer any difference… Now I realize that this feeling was completely wrong. The main module I optimized was a drawing module, so it uses many single-float geometric computation (I work on a 32 bits version of lw 5) and the result of optimization was amazing : with floats, it’s possible (in testing environment) to divide the time of computation by 50, or even more, and to reduce the consumption of memory to nothing. Practically, the drawing process of my application consumes now 40% of the time it consumed before (20% being the - irreducible - drawing itself), and less than 5% of the memory (before optimization, drawing the view completely can consume several MB). The gain is very noticeable, especially during scrolling, resizing, zooming and so on. But another observable result is that the codes are at least 2 times longer and more difficult to read. However, they are also safer and simpler to maintain because types are explicit.

During the process of optimization, my goal was to reduce the memory consumption of low-level functions used by this module to zero. Generally it was a good way to obtain a drastic reduction of the consumption of time. (float 0) is essential, but it must be combined with (safety 0) to obtain the « optimized environment ». If each variable going in an operator is typed, the compiler uses the typed version of this operator (you can see that when disassemble), the main gain of time is there. The main gain of space is to avoid boxing and unboxing numbers. So it is not a good idea to switch too often between optimized an non optimized environment. To store unboxed floats, the only solution is to use typed arrays (don’t trust type declarations in classes or structures : they never store raw values). Passing arguments between functions (even local functions like flet) can become difficult because optimized floats are boxed at this point. The only solution is to pass typed arrays (even single index arrays, equivalent to a kind of « customized box ») between functions, and/or to use inlined functions (and/or macros). So the type of each float variable should be declared if you plane to use it for computation (even in loops). The type of typed arrays should be declared too. Numeric constants must be typed (I mean 1.0 not 1). Global variables must be typed with « the » (no other solution, even if « the » is really not the best way to declare types) - the declaration (defvar *foo* (the single-float 1.0)) is useless.

for instance :
(defvar *increment* 1.0)

NON OPTIMIZED

(defun test () (loop for f = 1.0 then (+ f *increment*) while (< f 20) sum f))

(time (test)) => 190.0, 0ms, 340 bytes. (for 1.000.000 operations the time is 2.8 sec)

OPTIMIZED

(defun test ()
(declare (optimize (speed 3) (safety 0) (float 0)))
(let ((fbox (load-time-value (make-array 1 :element-type 'single-float)))) ;could be a macro 'with-fbox'
(declare (type (simple-array single-float 1) fbox))
(loop for f of-type single-float = 1.0 then (+ f (the single-float *increment*)) while (< f 20.0)
sum f into sum of-type single-float
finally (progn (setf (aref fbox 0) sum)
(return fbox)))))

(time (test)) => #(190.0), 0ms, 0 bytes. (for 1.000.000 operation the time is 0.04 sec… 70 times better)


Another source of acceleration (not so impressive than for float however) is with fixnums. The operators having always to check if a fixnum doesn’t overflow the range of 29 bits (becoming a bignum), If you have fixnum computation and know that it won’t overflow, the declaration of types combined with the use of (hcl:fixnum-safety 0) can add a significant acceleration.

Another source of optimization is the use of typed arrays. For instance, imagine two arrays of length 4, one with a default type T and another with a type single-float.

- the first needs 8 bytes for the array + 16 bytes for the 4 pointers to the boxed floats + 32 bits for the boxed floats themselves => 56 bytes
- the second needs 8 bytes for the array + 16 bytes for the 4 single-float => 24 bytes

Note that, if your read the typed array in a non optimized environment, it will consume 8 bytes each time when, boxed, it consumes nothing. But in optimized environment it’s something like the contrary… So the context, optimized or not, becomes very important to choose the type of storage.

There is another benefit of typed arrays but it’s hacking and certainly not portable : in optimized environment, you can read an array of single-float as a integer (the IEEE code), you can use an array of (unsigned-byte 32) as an array of (unsigned-byte 8) with 4 indexes instead of one, or even as a bit vector with 32 indexes instead of one... Simply pass the array to a function, and declare it as another (compatible) type. In the function, the new type will be used, when outside it’s the real type that is used.

Finally I am very happy with the result of this experience... but also troubled : After all this evolution, avoiding consing, using typed array, declaring the type of local variables, and so on… am I not in a kind of pseudo C environment ? except that the codes are less clear, the work at least two times longer, and the compiler a lot less helpful for the programmer that in, let’s say, xcode 5 ? Naturally it’s for a very specific module… but this module needs to speak with my lisp model so it can’t be implemented in pure C. So I believe that tools to build optimized and performant codes in lisp more simply could be very, very useful and a fantastic evolution for the language.

Best regards

Denis
------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles
+ 32 2 219 31 09
http://www.denispousseur.com
------------------------------------------------
Hi,
Is there a precise references for what combinations of declares/the's/etc. actually achieve improvements in the LW compiler and what improvements they achieve? The reference manual page on declare mentions that declaring types "removes type checking", what effects do other declarations have?
Mark
Ala'a Mohammad
2014-05-22 18:09:08 UTC
Permalink
LW provides the :explain declaration

http://www.lispworks.com/documentation/lw61/LW/html/lw-638.htm

In short it shows what is the compiler is trying to do.

(defun test ()
(declare (optimize (speed 3) (safety 0) (float 0)))
(declare (:explain :types))
(loop for f of-type single-float = 1.0 then (+ f (the single-float
*increment*))
while (< f 20.0) sum f into total of-type single-float
finally (return total)))

(compile 'test) ;; look at the compiler output.

HiH

Ala'a

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Denis Pousseur
2014-05-22 18:49:47 UTC
Permalink
Ah yes, very interesting !

For my point of view it deserves a panel that can write this information in a specialized output and that allow to activate or deactivate this functionality globally (a little bit like the toggle facility ?).

Anyway, it’s very cool to know that this option exist, I never hear about it before. Thanks !

Denis

------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles
+ 32 2 219 31 09
http://www.denispousseur.com
------------------------------------------------
Post by Ala'a Mohammad
LW provides the :explain declaration
http://www.lispworks.com/documentation/lw61/LW/html/lw-638.htm
In short it shows what is the compiler is trying to do.
(defun test ()
(declare (optimize (speed 3) (safety 0) (float 0)))
(declare (:explain :types))
(loop for f of-type single-float = 1.0 then (+ f (the single-float
*increment*))
while (< f 20.0) sum f into total of-type single-float
finally (return total)))
(compile 'test) ;; look at the compiler output.
HiH
Ala'a
_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Martin Simmons
2014-05-28 17:19:50 UTC
Permalink
Nice post!

One minor addition: you can type global variables with declaim as a top level
form.

(defvar *increment* 1.0)
(declaim (type single-float *increment*))
--
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/
Post by Denis Pousseur
Dear list,
I just spent several month to optimize some modules of my application. I would like to add some comments about this interesting experience. Thanks for any comment or corrections because I have always a lot of things to learn from you.
Before this experience, I really never understand nothing about this question of optimization because, when I test it, (speed 3) generally doesn’t offer any difference… Now I realize that this feeling was completely wrong. The main module I optimized was a drawing module, so it uses many single-float geometric computation (I work on a 32 bits version of lw 5) and the result of optimization was amazing : with floats, it’s possible (in testing environment) to divide the time of computation by 50, or even more, and to reduce the consumption of memory to nothing. Practically, the drawing process of my application consumes now 40% of the time it consumed before (20% being the - irreducible - drawing itself), and less than 5% of the memory (before optimization, drawing the view completely can consume several MB). The gain is very noticeable, especially during scrolling, resizing, zooming and so on. But another observable result is that the codes are at least 2 times longer and more difficult to read. However, they are also safer and simpler to maintain because types are explicit.
During the process of optimization, my goal was to reduce the memory consumption of low-level functions used by this module to zero. Generally it was a good way to obtain a drastic reduction of the consumption of time. (float 0) is essential, but it must be combined with (safety 0) to obtain the « optimized environment ». If each variable going in an operator is typed, the compiler uses the typed version of this operator (you can see that when disassemble), the main gain of time is there. The main gain of space is to avoid boxing and unboxing numbers. So it is not a good idea to switch too often between optimized an non optimized environment. To store unboxed floats, the only solution is to use typed arrays (don’t trust type declarations in classes or structures : they never store raw values). Passing arguments between functions (even local functions like flet) can become difficult because optimized floats are boxed at this point. The only solution is to pass typed arrays (even single index arrays, equivalent to a kind of « customized box ») between functions, and/or to use inlined functions (and/or macros). So the type of each float variable should be declared if you plane to use it for computation (even in loops). The type of typed arrays should be declared too. Numeric constants must be typed (I mean 1.0 not 1). Global variables must be typed with « the » (no other solution, even if « the » is really not the best way to declare types) - the declaration (defvar *foo* (the single-float 1.0)) is useless.
(defvar *increment* 1.0)
NON OPTIMIZED
(defun test () (loop for f = 1.0 then (+ f *increment*) while (< f 20) sum f))
(time (test)) => 190.0, 0ms, 340 bytes. (for 1.000.000 operations the time is 2.8 sec)
OPTIMIZED
(defun test ()
(declare (optimize (speed 3) (safety 0) (float 0)))
(let ((fbox (load-time-value (make-array 1 :element-type 'single-float)))) ;could be a macro 'with-fbox'
(declare (type (simple-array single-float 1) fbox))
(loop for f of-type single-float = 1.0 then (+ f (the single-float *increment*)) while (< f 20.0)
sum f into sum of-type single-float
finally (progn (setf (aref fbox 0) sum)
(return fbox)))))
(time (test)) => #(190.0), 0ms, 0 bytes. (for 1.000.000 operation the time is 0.04 sec… 70 times better)
Another source of acceleration (not so impressive than for float however) is with fixnums. The operators having always to check if a fixnum doesn’t overflow the range of 29 bits (becoming a bignum), If you have fixnum computation and know that it won’t overflow, the declaration of types combined with the use of (hcl:fixnum-safety 0) can add a significant acceleration.
Another source of optimization is the use of typed arrays. For instance, imagine two arrays of length 4, one with a default type T and another with a type single-float.
- the first needs 8 bytes for the array + 16 bytes for the 4 pointers to the boxed floats + 32 bits for the boxed floats themselves => 56 bytes
- the second needs 8 bytes for the array + 16 bytes for the 4 single-float => 24 bytes
Note that, if your read the typed array in a non optimized environment, it will consume 8 bytes each time when, boxed, it consumes nothing. But in optimized environment it’s something like the contrary… So the context, optimized or not, becomes very important to choose the type of storage.
There is another benefit of typed arrays but it’s hacking and certainly not portable : in optimized environment, you can read an array of single-float as a integer (the IEEE code), you can use an array of (unsigned-byte 32) as an array of (unsigned-byte 8) with 4 indexes instead of one, or even as a bit vector with 32 indexes instead of one... Simply pass the array to a function, and declare it as another (compatible) type. In the function, the new type will be used, when outside it’s the real type that is used.
Finally I am very happy with the result of this experience... but also troubled : After all this evolution, avoiding consing, using typed array, declaring the type of local variables, and so on… am I not in a kind of pseudo C environment ? except that the codes are less clear, the work at least two times longer, and the compiler a lot less helpful for the programmer that in, let’s say, xcode 5 ? Naturally it’s for a very specific module… but this module needs to speak with my lisp model so it can’t be implemented in pure C. So I believe that tools to build optimized and performant codes in lisp more simply could be very, very useful and a fantastic evolution for the language.
Best regards
Denis
------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles
+ 32 2 219 31 09
http://www.denispousseur.com
------------------------------------------------
Hi,
Is there a precise references for what combinations of declares/the's/etc. actually achieve improvements in the LW compiler and what improvements they achieve? The reference manual page on declare mentions that declaring types "removes type checking", what effects do other declarations have?
Mark
_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Denis Pousseur
2014-05-28 19:20:09 UTC
Permalink
Post by Martin Simmons
One minor addition: you can type global variables with declaim as a top level
form.
(defvar *increment* 1.0)
(declaim (type single-float *increment*))
Ah yes… so I can use a macro to do something like :

(def-typed-var *increment* single-float 1.0)

Good to know : thanks !

Denis

------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles
+ 32 2 219 31 09
http://www.denispousseur.com
------------------------------------------------
Pascal J. Bourguignon
2014-05-29 14:18:39 UTC
Permalink
Post by Martin Simmons
Nice post!
One minor addition: you can type global variables with declaim as a top level
form.
(defvar *increment* 1.0)
(declaim (type single-float *increment*))
You cannot declaim that! You've not checked that
*read-default-float-format* is single-float, so *increment* could be of
another float type.

You should write either:

(setf *read-default-float-format* 'single-float)
(defvar *increment* 1.0)
(declaim (type single-float *increment*))

or:

(defvar *increment* 1.0)
(eval-when (:compile-toplevel :load-toplevel :execute)
(proclaim `(type ,*read-default-float-format* *increment*)))


or:

(defvar *increment* 1.0f0)
(declaim (type single-float *increment*))
--
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ? C'est le moment d'acheter !"

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Martin Simmons
2014-05-29 15:51:53 UTC
Permalink
Post by Pascal J. Bourguignon
Post by Martin Simmons
Nice post!
One minor addition: you can type global variables with declaim as a top level
form.
(defvar *increment* 1.0)
(declaim (type single-float *increment*))
You cannot declaim that! You've not checked that
*read-default-float-format* is single-float, so *increment* could be of
another float type.
(setf *read-default-float-format* 'single-float)
(defvar *increment* 1.0)
(declaim (type single-float *increment*))
(defvar *increment* 1.0)
(eval-when (:compile-toplevel :load-toplevel :execute)
(proclaim `(type ,*read-default-float-format* *increment*)))
(defvar *increment* 1.0f0)
(declaim (type single-float *increment*))
Yes, good point (though the original use of "the" had the same problem).
--
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Pascal J. Bourguignon
2014-05-29 14:22:26 UTC
Permalink
Post by Martin Simmons
Nice post!
One minor addition: you can type global variables with declaim as a top level
form.
(defvar *increment* 1.0)
(declaim (type single-float *increment*))
No, you cannot declaim that! You've not checked that
*read-default-float-format* is single-float, so *increment* could be of
another float type.

You should write either:

(setf *read-default-float-format* 'single-float)
(defvar *increment* 1.0)
(declaim (type single-float *increment*))

or:

(defvar *increment* 1.0)
(eval-when (:compile-toplevel :load-toplevel :execute)
(proclaim `(type ,*read-default-float-format* *increment*)))


or:

(defvar *increment* 1.0f0)
(declaim (type single-float *increment*))
--
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ? C'est le moment d'acheter !"

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Denis Pousseur
2014-05-29 15:49:22 UTC
Permalink
Post by Pascal J. Bourguignon
No, you cannot declaim that! You've not checked that
*read-default-float-format* is single-float, so *increment* could be of
another float type.
(setf *read-default-float-format* 'single-float)
could I do this once for all at startup...
Post by Pascal J. Bourguignon
(defvar *increment* 1.0)
(declaim (type single-float *increment*))
...and after declare the variables as Martin told me ?

Thanks

------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles
+ 32 2 219 31 09
http://www.denispousseur.com
------------------------------------------------


_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Pascal J. Bourguignon
2014-05-29 16:45:34 UTC
Permalink
Post by Denis Pousseur
Post by Pascal J. Bourguignon
No, you cannot declaim that! You've not checked that
*read-default-float-format* is single-float, so *increment* could be of
another float type.
(setf *read-default-float-format* 'single-float)
could I do this once for all at startup...
And what good would that do to people loading your code in other
environments?

Sure, you could and probably should set it up in your rc files, but you
should also explicitely set it in your source files, if you depend on
it.
Post by Denis Pousseur
Post by Pascal J. Bourguignon
(defvar *increment* 1.0)
(declaim (type single-float *increment*))
...and after declare the variables as Martin told me ?
But if you depend on a specific float type for a given variable, you
should probably better explicitely give a specifically typed literal
such as 1.0f0.
--
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ? C'est le moment d'acheter !"

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Denis Pousseur
2014-06-05 09:32:35 UTC
Permalink
Post by Pascal J. Bourguignon
Post by Denis Pousseur
Post by Pascal J. Bourguignon
No, you cannot declaim that! You've not checked that
*read-default-float-format* is single-float, so *increment* could be of
another float type.
(setf *read-default-float-format* 'single-float)
could I do this once for all at startup...
And what good would that do to people loading your code in other
environments?
Actually I don’t share my codes with anybody, but you’re right, in a case like that, it could be a good idea to set this variable in a kind of « header » for each module.
Post by Pascal J. Bourguignon
Sure, you could and probably should set it up in your rc files, but you
should also explicitely set it in your source files, if you depend on
it.
Post by Denis Pousseur
Post by Pascal J. Bourguignon
(defvar *increment* 1.0)
(declaim (type single-float *increment*))
...and after declare the variables as Martin told me ?
But if you depend on a specific float type for a given variable, you
should probably better explicitely give a specifically typed literal
such as 1.0f0.
Well, a large majority of floating point numbers in my drawing module are directly related to the type ‘CGFloat' of the Mac’s CoreGraphics frameworks. This type is a single-float in 32bits environments and a double in 64bits environments. My codes are actually developed with a 32bits version of LW, but if they have to be ported on a 64 bits version in the future, it will be simpler to change the declaration of a single global variable than to change each float constant. So I prefer to keep a non explicit notation in general and use only explicit notation for other (and exceptional) types. The variable you invoke seems to be a perfect tool for this situation : thank’s to point it.

(the default value of this variable is single-float so, in fact, I have no problem with it actually... except if the system can change it’s value. It was the sense of my question. But, reading from the doc - even if it’s not completely explicit -, it seems that the programmer is responsible of this variable and that the system never change it).

Thanks for you comments
------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles
+ 32 2 219 31 09
http://www.denispousseur.com
------------------------------------------------
Post by Pascal J. Bourguignon
--
__Pascal Bourguignon__
http://www.informatimago.com/
"Le mercure monte ? C'est le moment d'acheter !"
_______________________________________________
Lisp Hug - the mailing list for LispWorks users
http://www.lispworks.com/support/lisp-hug.html
_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Robert Smith
2014-05-28 17:52:50 UTC
Permalink
On Thu, May 22, 2014 at 3:01 AM, Denis Pousseur
Post by Denis Pousseur
Finally I am very happy with the result of this experience... but also
troubled : After all this evolution, avoiding consing, using typed array,
declaring the type of local variables, and so on… am I not in a kind of
pseudo C environment ? except that the codes are less clear, the work at
least two times longer, and the compiler a lot less helpful for the
programmer that in, let’s say, xcode 5 ? Naturally it’s for a very specific
module… but this module needs to speak with my lisp model so it can’t be
implemented in pure C. So I believe that tools to build optimized and
performant codes in lisp more simply could be very, very useful and a
fantastic evolution for the language.
Indeed, you are coding closer to the way you would in C. Is this
unexpected, and could it be avoided? I don't think so.

Things could be improved by better semantic analysis in the compiler:
extended lifetime analysis, type propagation and inference, interval
analysis, and so on. That would remove some of the burden from the
Lisp programmer.

However, I wouldn't say that XCode 5 would be a better place to do
development in, principally because if you're down to the C level,
you're locked in it. I can't prototype, modify safety settings as
much, and so on.

An experienced Lisp programmer who is very adept with his or her
compiler of choice can produce a reasonably equivalent to a C
programmer in the same, if not shorter time. And more likely than not,
the Lisp programmer's program will be safer and better debugged. It's
true that C-like Lisp is longer than just C, but that's because Lisp
makes all unsafe points/performant points/etc more explicit.

Cheers,

Robert

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Denis Pousseur
2014-06-05 09:39:12 UTC
Permalink
Post by Robert Smith
On Thu, May 22, 2014 at 3:01 AM, Denis Pousseur
Post by Denis Pousseur
Finally I am very happy with the result of this experience... but also
troubled : After all this evolution, avoiding consing, using typed array,
declaring the type of local variables, and so on… am I not in a kind of
pseudo C environment ? except that the codes are less clear, the work at
least two times longer, and the compiler a lot less helpful for the
programmer that in, let’s say, xcode 5 ? Naturally it’s for a very specific
module… but this module needs to speak with my lisp model so it can’t be
implemented in pure C. So I believe that tools to build optimized and
performant codes in lisp more simply could be very, very useful and a
fantastic evolution for the language.
Indeed, you are coding closer to the way you would in C. Is this
unexpected, and could it be avoided? I don't think so.
extended lifetime analysis, type propagation and inference, interval
analysis, and so on. That would remove some of the burden from the
Lisp programmer.
Yes, it should be great
Post by Robert Smith
However, I wouldn't say that XCode 5 would be a better place to do
development in, principally because if you're down to the C level,
you're locked in it. I can't prototype, modify safety settings as
much, and so on.
It depends on the situation. For instance, with a model in C, you can write codes that use the model in Lisp, thanks to the FLI. But with a model in lisp you are locked in Lisp… Naturally, a model in lisp is much more attractive and powerful but, sometime, the question of compatibility with the rest of the world is also very important.
Post by Robert Smith
An experienced Lisp programmer who is very adept with his or her
compiler of choice can produce a reasonably equivalent to a C
programmer in the same, if not shorter time.
With a C compiler, all the graph of interactions between functions is safe at compile time. This is a very significant benefit, and logically a gain of time at debug time. Most of the time, when my C library compiles, it is free of bug. I can’t say that in lisp... and it’s not so easy to test efficiently a run-time environment. So if the compiler can make a generous part of the job, I appreciate :-)
Post by Robert Smith
And more likely than not,
the Lisp programmer's program will be safer and better debugged. It's
true that C-like Lisp is longer than just C, but that's because Lisp
makes all unsafe points/performant points/etc more explicit.
Personally I hate xcode for debugging, but it's because I don’t have any practice of assembler... Debugging is great in LW. However, in the optimized environment it’s a little bit different. The function containing the error is generally found, but the portion of code pointed by the debugger is also generally wrong (at least in lw5). It’s necessary to unoptimize the function and run again to have a correct debugging. But even like that, it stays a lot better than Xcode.

However, xcode 5 has great tools for versioning, refactoring, work with nib files, internationalization files, XML files, and so on. Personally I have my whole project in xcode : C codes, xml codes, Nibs and resources, and even lisp codes. I use it, for instance, to find and replace symbols into the whole lisp project or to compare quickly different versions of a same file (when needed, xcode can open the file in LW directly). I cannot do that in LW, so for the organization of a large project, it’s really a great help. For me LW and Xcode are now perfectly complementary.

Thanks for your comments

Denis
Post by Robert Smith
Cheers,
Robert
------------------------------------------------
Denis Pousseur
70 rue de Wansijn
1180 Bruxelles
+ 32 2 219 31 09
http://www.denispousseur.com
------------------------------------------------

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Martin Simmons
2014-06-05 17:53:04 UTC
Permalink
Post by Denis Pousseur
... Debugging is great in LW. However, in the optimized environment it’s a
little bit different. The function containing the error is generally found,
but the portion of code pointed by the debugger is also generally wrong (at
least in lw5). It’s necessary to unoptimize the function and run again to
have a correct debugging. But even like that, it stays a lot better than
Xcode.
If you have any self-contained examples of how it is wrong with optimized
code, then please let us know on lisp-support.
--
Martin Simmons
LispWorks Ltd
http://www.lispworks.com/

_______________________________________________
Lisp Hug - the mailing list for LispWorks users
lisp-***@lispworks.com
http://www.lispworks.com/support/lisp-hug.html
Loading...