how 'expensive' is calling getMetadata() on an obj...
# cfml-general
w
how 'expensive' is calling getMetadata() on an object? i have a recursive function where i may need to call getMetadata at every level of recursion on an argument being passed in and don't want any significant overhead
s
I think it's pretty expensive, especially on older engines. typically the metadata is cached somewhere if it's going to be reused
w
the udf i have is recursing into a struct, which may of course of nested arrays, structs and other objects. i had it evaluating the metadata 'at the top', once, but i don't think i can get away from reevaluating each object being passed in recursively. if that makes sense
s
I think I'd just make a metadata library somewhere and refer to it rather than 'figuring it out' in each udf call
m
OK so I had a client who was having major issues with performance. They were on CF11 prior to my arriving. We moved them to CF2018. The performance improved by about 20-30%, but it was still a killer. Figured out they were doing a deep recursion getMetadata() on hundreds of objects on a page. But the reason why was a limit in how JSON was read in CF11, so we were able to refactor it. The performance went up something like 3000%. So, in short, it is massively expensive, most especially in the case you're describing. In fact, it almost sounds like exactly the same case as ours (except we fixed it)
w
ok, thanks for that feedback then
b
@websolete This function used to be a dog in both engines, and especially ACF but it's gotten a lot faster. The main issue is whether or not it's the first time you've called it since the actual compilation of the CFC is what takes time. Both CF engines have some level of caching internally for the actual metadata.
m
If the objects don't change you could try to read in the meta-data and keep it in a lookup. Just batch it offline. That's the best idea I'd come up with if they had decided not to move up to 2018. And in their case, it would not work as it was class data for a UC and changed a LOT
b
WireBox/ColdBox suffers a lot from this overhead in large CFC-heavy apps, but mostly when the server is just starting up. This is why we added a WireBox feature to point to a CacheBox cache which I tie into a file system cache in CommandBox to improve startup time.
w
let me explore an alternate solution then: i have structs that may have readonly objects like cfcatch in them. what i really need to know is when an object is 'special'. isstruct(java-readonlyobject) will return false, even though you can traverse it with struct bifs. is there a 'good' way of determining whether an object is special?
b
@websolete This will be engine-specific, but I'd do
Copy code
obj.getClass().getName()
and introspect that
It's very performant and works on any CF variable
I'm assuming those read only structs will be a different actual Java class behind the scenes
Just make sure you account for the different types of structs that CFML has built in (sorted, etc) as they all have different implementing sub classes
w
that would work, thanks
solves my problem, as i was actually using getMetadata to simply get the name value anyway.