5 ms·
> Lisp also makes use of vectors, where necessary. These languages with managed memory like Java have the same object/reference model as Lisp and the same calli
by kerkeslager 2y ago
> Lisp also makes use of vectors, where necessary. These languages with managed memory like Java have the same object/reference model as Lisp and the same calling mechanisms. linked lists are only a special case (-> java.util.LinkedList).
You seem insistent on missing my point.
"Where necessary?" is almost always, because vectors almost always outperform linked lists based on cons cells. If your program uses cons cells at all, chances are you made the wrong choice. Lisp doesn't make use of vectors in many cases "where necessary" because "where necessary" is a whole lot more than Lisp's structure, libraries, and community encourage you to do.
Simply pointing out that java.util contains a Linked List implementation means nothing. I wrote Java full time professionally for ~5 years and never saw that used once. If Python or C# ship with linked list implementations I'm not aware of them because they're also never used.
To be frank, if your program uses linked lists at all, it's probably a mistake from a performance perspective. There simply aren't many cases where a linked list is a better choice than a vector. And this is a mistake that Lisp programs make all the time because cons cells are so baked into the language.
> > in most languages it does not entail pointer chasing
> It does, see above. Just not tail pointers in the list.
It is both dishonest and rude to not even quote a full sentence when you're trying to refute something.
Tail pointers on the list being avoided is exactly my point, a fact which you obfuscated by removing context. That is a huge amount of added cache thrashing, even with cache-aware allocation. This is not something you can just pretend is a minor issue.
Are you even capable of admitting that Lisp has serious faults, or do you really think it's completely, 100% perfect? This isn't a rhetorical question: I legitimately would like to hear what serious faults you think Lisp has, because if you can't present any problems with Lisp at all, then you simply aren't capable of participating usefully in conversations about Lisp. Lisp is a human invention which includes human mistakes, and if you can't admit that, anything you say about it is going to suffer from crippling bias and can't be trusted.
And to be clear, I'm not interested in further whataboutism. If your idea of a problem with Lisp is something where you can end with "but every other language has this problem too", stop--that's just further proving your inability to criticize Lisp. I'm happy to describe serious problems unique to any of the languages I've mentioned in this thread, but that's not the current topic of discussion.
Pointer chasing in linked lists is a cause of performance problems in Lisp and it isn't a cause of performance problems in other languages. No, not for retrieving each individual item, I'm talking about moving from one item to the next. Every single thing you've said in this thread has been trying to move the goalposts to make it seem like this isn't a problem or it isn't unique to Lisp. It is a problem. It is unique to Lisp(s).
- lispm 2y ago> "Where necessary?" is almost always, because vectors almost always outperform linked lists based on cons cells. Let's see, I have here a Common Lisp compiling to machine code, here non-optimized generic Lisp code: I'm allocating n elements list/vector of vectors and reverse it p times. reversing allocates a new list/vector. (defun test1 (n p) (let ((v (make-array n))) (map-into v (lambda () (make-array 10 :initial-element 1000))) (loop repeat p do (setf v (reverse v))) v)) (defun test2 (n p) (let ((l (make-list n))) (map-into l (lambda () (make-array 10 :initial-element 1000))) (loop repeat p do (setf l (reverse l))) l)) CL-USER 15 > (time (test1 10000 100)) Timing the evaluation of (TEST1 10000 100) User time = 0.005 System time = 0.000 Elapsed time = 0.003 Allocation = 9088696 bytes 1 Page faults GC time = 0.000 #(# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ...) CL-USER 16 > (time (test2 10000 100)) Timing the evaluation of (TEST2 10000 100) User time = 0.008 System time = 0.001 Elapsed time = 0.006 Allocation = 17113288 bytes 842 Page faults GC time = 0.003 (# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ...) The list or vector is 10000 elements long and 100 times reversed and the difference in runtime is tiny. The list version is only marginally slower, but allocates a lot more memory. I can also construct cases, where the list is much faster. Adding a one element list/vector to the front: CL-USER 22 > (time (test1 10000 100)) Timing the evaluation of (TEST1 10000 100) User time = 0.016 System time = 0.000 Elapsed time = 0.012 Allocation = 9148776 bytes 0 Page faults GC time = 0.000 #(A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A ...) CL-USER 26 > (time (test2 10000 100)) Timing the evaluation of (TEST2 10000 100) User time = 0.000 System time = 0.000 Elapsed time = 0.000 Allocation = 1042248 bytes 0 Page faults GC time = 0.000 (A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A A ...) Here the runtime for lists is much faster, since it does not copy the complete list or -> lists share storage, consing to the front is cheap. -> for many practical use cases for lists the total runtime and the runtime difference does not matter Obviously there are also many case where a list would perform much worse, like accessing the last element of a list. > Are you even capable of admitting that Lisp has serious faults You seem to be keen to find "faults". Usually things are not black and white. There is no true and false, but engineering trade-offs. These tradeoffs can Lisp make the wrong choice for problems. Many of the trade-offs are also influenced by non-technical issues: like the amount of engineering time invested into a language implementation: see SUN/Oracles investment into Java.