freenode/#lisp - IRC Chatlog
Search
17:42:50
beach
Right now, I am working on trying to understand (and explain in the spec) Doug Lea's memory allocator and how I will adapt it for use in SICL.
17:44:57
beach
jasom: But I think you are right. The old problem of references from an old to a young generation will likely pop up if you try that.
17:45:29
jeosol
jmercouris: really? hmmm. Not sure what the competition is doing. Or may be few references so far.
17:46:48
beach
jasom: I am off to spend time with my (admittedly small) family. I'll be back tomorrow morning (UTC+2).
18:08:55
drmeister
The optimization where calls within a compilation unit can be called directly without going through symbol-function - does anyone know where that is described in the CLHS?
18:22:09
jasom
the "inline" declaration implicitly 3 states, with the default state not one that you can declare
18:42:31
scymtym__
there is also (declaim (inline …)) (defun …) (declaim (notinline …)) which can mean "don't inline by default but respect local inline declarations"
18:45:18
Inline
a sequential inline notinline, i would have thought that would be just temporary inlining
18:46:58
Inline
i.e. hop to it's place and turn back where you left off instead of copying and expanding it's code
18:49:09
scymtym__
the initial inline declaration prepares the function for inlining *and* makes inlining the default behavior. the subsequent notinline declaration leaves the function prepared for inlining but changes the default behavior back to not inlining. after that, the function is still prepared for inlining which can be requested, for example, via (locally (declare (inline …)))
19:04:29
pjb
scymtym__: this is wrong. notinline has nothing to do with inlining, and everything to do with notinlining.
19:07:49
pjb
Notably, it does nothing to the function, those declarations only concern the calls to the function, not the function itself.
19:09:48
scymtym__
the sentence that starts with "To define a function f that is not inline by default …" seems to be about the definition
19:09:58
pjb
The idiom in question has the effect of letting the compiler compile some recursive calls as inline calls (which can be done, surprisingly). If you had the notinline before, then this optimization wouldn't be available to the compiler. But that's the only effect of this order.
19:11:26
pjb
The only thing, is that having the inline declaration before the function helps the compiler to book-keep information for inlining.
19:11:50
pjb
notice that the compiler is allowed to inline function calls to functions defined inside the same compilation-unit anyways!
19:12:16
pjb
Therefore this book-keeping stuff is bullshit: the compilers are already allowed to keep the information whatever declaration you put.
19:15:50
pjb
Also, a compiler can compile a function call as being both inline and notinline. Because semantically, the effect of notinline is actually that the function call (foo …) is AS IF (funcall (symbol-function 'foo) …). So the compiler may call the function inline (copy the source of the function in place of the function call), AND keep track of the dependency of the caller to the callee, so when the callee is redefined (setf
19:44:34
p_l
hmm, would taking a tag bit for "this is forwarding pointer" and having possibility of reading it instead of header work?.... hmmm
20:57:36
jmercouris
is it enough to have a top-level statement that invokes a function to load this data from the database and then dump the image?
21:01:29
rpg
jmercouris: probably.... depends a lot on what you want to do with the data. Also, you probably want to tear down the database connection before you dump the image.
21:02:24
jmercouris
which leads me to another question, will having a large hash-table persisted in my image slow down my application start-up time?
21:02:32
rpg
jmercouris: That should be fine then, but notice that you don't want an image with a half-open database connection!
21:03:44
jmercouris
I'm talking about a very large hash table, perhaps one that has around 100,000 entries
21:03:50
rpg
jmercouris: I believe the answer is "no," but it's pretty dependent on implementation, memory, etc. The basic notion is that you are pulling the full image in and that's faster than taking a fasl and doing all the things involved in loading it.
21:04:16
jmercouris
I need my program to start almost instantaneously, and then load this information in memory
21:06:34
rpg
If your users are definitely going to need this table, then there's no reason to load it lazily, and I believe this is the fastest way to load it.
21:06:57
jmercouris
I just would like to give them an opportunity to begin typing before the table is completely loaded into memory
21:08:12
rpg
Then this should be the fastest way to get it loaded. I don't know if there's any way to optimize the memory layout (e.g., to keep the hash table in contiguous memory) before dumping. I'd definitely suggest creating the hash table with a known-big-enough :size argument -- that might improve the initial memory layout.
21:08:41
rpg
I wonder if you can somehow shove it into old memory, since you are never going to want it garbage-collected.
21:17:06
rpg
jmercouris: You don't want the garbage collector to bother looking at this table -- you know it's going to stay around. It might help make your program more efficient to find a way (this would definitely be SBCL-specific) to tell the lisp environment that this is permanent memory so it can be hidden from the garbage collector.
21:27:17
whartung
Yea, mmap. Store it “off heap”, GC never even knows it exists, but you get to handle all the access and marshalling of stuff — which is a pain.
21:28:31
whartung
(and then you think “why not store it in a db and let it cache it anyway, isn’t that what they’re for?”)
22:56:50
didi
Decisions, decisions... should I start using ENDP, instead of NULL, to test for the end of a list?
23:04:40
pjb
whartung: if you use mmap, you may use com.informatimago.common-lisp.heap.heap to store lisp objects in it.
23:07:14
didi
In another news, I recently discovered LOOP's keyword NCONC. It took me long enough. :-P
23:07:23
pjb
Now, it's not native lisp objects, so it may be a draw back, but it allows to share lisp objects (using shared memory) with other implementations, so it may be an advantage.
23:18:54
didi
And a nitpick: LOOP's keywords for hash-tables are confusing. Using [each, the, in, of] makes no difference, but I was trained that using [in, on] with list does.
23:36:58
White_Flame
ugh, yet another (vector (unsigned-byte 8)) vs (simple-array (unsigned-byte 8)) mismatch, this time with cl-sqlite
23:48:37
aeth
destructuring-bind takes a while to get used to, but it has replaced almost all of my old ways of parsing lists because usually there's *some* structure
23:49:45
aeth
And for iterating, I usually use do-destructuring-bind (dolist with destructuring-bind) or a higher order function with destructuring-lambda (lambda with one argument, on which a destructuring bind is applied)
23:50:03
aeth
destructuring-bind gets annoying with iteration unless you build trivial abstractions like that to flatten it
23:50:32
aeth
Alternatively, there are general macros to flatten stuff, but it's probably more intended for with-foo, let, multiple-value-bind, destructuring-bind, etc., stacking together, rather than being used in an iteration
23:56:40
aeth
definitely an option but it's very heavyweight compared to a handful of trivial macros on top of built-in forms
0:18:35
didi
By using `destructuring-bing', I feel I won't be able to freely change a data structure implementation. So, If I say (destructuring-bind (a . b) foo ...), `foo' is set to be a cons, with `a' as the `car' and `b' as the `cdr'.
0:19:27
aeth
If you use destructuring-bind, you can usually tell if something doesn't match what you expect pretty quickly. If you use cadr or whatever, you might never refactor it properly
0:19:48
mfiano
If it's built out of conses, it is trivial to parse with destructuring-bind. You argument holds better for arrays or hash tables.
0:21:11
aeth
If you're calling (cadr foo) and (caddr foo) through inline accessor functions you're probably going through the list twice (and certainly if they're not inline), and you could have nonsense at the end unless you do another check.
0:27:10
aeth
Sometimes you have no choice, though, like in macros (okay, you can probably use a reader macro to create structs at compile-time and use make-load-form-saving-slots to save the compile-time object so it's handled as a constant at runtime... but why?)
0:32:56
aeth
I find that either accessor functions or destructuring-bind (assuming it's not in a macro) is usually the first step to replacing it with a data structure, though
0:34:50
pjb
and if at any time you're worried about evolutivity of an implementation choice, you can always wrap it in a macro. Don't use destructuring-bind, use your own macro, that could expand to either that, or a with-accessors or a with-slots or something else.
0:38:41
aeth
pjb: I usually hide complicated things behind symbol-macrolet or with-accessors or something similar
0:40:34
pjb
didi: that is, it's better if you have to use it several times, or if it has to have an implementation that should be consistent with some other such macro or operator.
0:40:58
pjb
it is easier to ensure consistency in a mechanism, when it is implemented independently and separately from the rest of the code.
0:41:31
pjb
Also having such abstractions helps when you need to debug, since you can easily instrument those abstractions (add checks).
0:43:02
pjb
Yes. There are quick and easy checks that you can add when debugging and leave in production, but you can also add heavy checks (things that walk whole data structures, or perform complex computations to validate).
0:44:00
pjb
Note that I speak generally, here, not specifically for CL. I'm currently working on FreeRDP written in C, and it's horrible.
0:44:09
aeth
I created a typed cons cell out of structs that's about 30% slower than the built-in cons, but it saves having to walk the data structure to verify things (just check the type in O(1))
0:45:42
pjb
note that clisp can be compiled with a clisp compilation time option to add a slot to cons cells for your own usage.
0:47:10
aeth
Using structs is mostly portable because :type on a slot is usually at least somewhat respected. Full portability would require testing implementation behavior and wrapping the or check-type in places where it isn't respected on various implementations.
0:48:20
pjb
check-type must not be used indiscriminately. Sometimes you must rely on the intrinsic type checking.
2:00:54
nowhere_man
I'm starting to understand the concept of delimited continuations in the basic theory, but now I wonder: what are their typical uses?
2:10:09
White_Flame
delimited continuations are basically registering an lambda event handler from within a closure, for example
3:15:48
didi
krwq: I dislike doc generators, so I have no recommendation. But, I like this article: http://stevelosh.com/blog/2013/09/teach-dont-tell/
3:40:16
jasom
krwq: somewhat out-of-date, but: https://sites.google.com/site/sabraonthehill/lisp-document-generation-apps