The main goal here is to reduce the number of times thread-local data has to be looked up using e.g. `EnumerableThreadSpecific.local()`. While this isn't a bottleneck in many cases, it is when the action performed on the local data is very short and that happens very often (e.g. logging used sockets during geometry nodes evaluation). The solution is to simply pass the thread-local data as parameter to many functions that use it, instead of looking it up in those functions which generally is more costly. The lazy-function graph executor now only looks up the local data if it knows that it might be on a new thread, otherwise it uses the local data retrieved earlier. Alongside with `UserData` there is `LocalUserData` now. This allows users of the lazy-function evaluation (such as geometry nodes) to have custom thread-local data that is passed to all the lazy-functions automatically. This is used for logging now.