-
Notifications
You must be signed in to change notification settings - Fork 372
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Core] Text measure cache assumes that strings are immutable (and can return stale values) #225
Comments
Hello, thanks for raising this issue. Apologies that it isn't documented better. |
I don't think that would be particularly helpful in my use case, even though it would be reasonable enough for the simplified test case above. In my case, I'm calling the library from rust, passing through pointers to heap allocated strings. In the case I ran in to, it wasn't that the content of a string was being regenerated between layouts. What happened was that I passed a string during one layout, then that string was freed, and on the next layout frame a new string was allocated with the same underlying heap pointer but completely different content. So there's no obvious way to know that the pointer is reused and bump an associated It would be possible to work around this by building infrastructure on the rust side to avoid this occurring, but it seems fairly unexpected for the case above to not work, I think. |
I just ran into this same issue. A cacheKey would be a solution, but maybe it would be better to provide an |
For anyone who runs into this before there is a good solution, here is my hack in
This performs fine for my application with only very short strings... Of course this could be a decent slowdown if you have walls of text. |
@gw3583 I see, in that case, how about a bool in the text config that hashes the contents of the string instead of the pointer? It's a performance concern for apps that render documents, but should be totally fine if it's opt in 🙂 |
@Pleune you read my mind! |
Yup, that sounds great to me, thanks! |
Just to clarify - that will work 99.9% of the time, but will fail when you have two strings that result in a hash collision, right? To be resistant to hash collisions, it would need to also store and compare the string after the hash id check. |
@gw3583 yes you're right, I'll think of a solution 👍 |
I've created #238 as a halfway solution to this problem, with two caveats:
|
Thanks for the impressive work on this library.
Perhaps this issue is intended behavior, though I didn't notice it in the documentation? It seems like a foot gun that should be documented if intended behavior, but I think it should probably be made to handle the case below correctly.
If you pass a dynamically allocated string to
CLAY_TEXT
where the content subsequently changes next layout (but the lifetime of the string buffer remains valid), the code that caches text measurements can return stale values, because it only checks the value of the pointer when hashing for the id, rather than the content of the string.The test case below demonstrates the issue. It asserts by default as it returns a stale measurement for the text buffer the second time layout occurs. If you comment out the cache hit here:
clay/clay.h
Line 1655 in c3fcf6c
Then the test case passes.
One potential fix would be to copy the string content when updating / checking a cache item, making use of the existing
dynamicStringData
array. Then, when checking if the hash entry is valid, the string itself could be compared rather than the pointer (after the main hash check), though managing the lifetimes of those strings may be slightly complicated if they are retained in that cache.The text was updated successfully, but these errors were encountered: