07-06-05, 07:36 PM | #21 |
Yep, it does seem to report increments of 1 millisecond. (If you run GetTime() in a loop just printing it to chat, the values are precisely increments of 1 millisecond.) I'm not sure the time is accurate to the millisecond though -- are all milliseconds created equal?
The other problem is that a lot of functions run much quicker than a millisecond. Lua is running about 1,000+ OnEvent/OnUpdate functions per second. That probably fans out to 5,000+ functions per second. I'll show timing data in v1.4 though. You've helped me convince myself that it's not that big of a problem. I should just try simple timing and see what happens. |
|
07-14-05, 06:03 PM | #22 |
A very nice AddOn
I have just noticed this AddOn thanks to the publicity it received on the official forums. Good job, Iriel :-) It does look very nice and very useful. However, I would like to make a couple of small comments:
1) In make_hook, you create a function that has ellipsis (...) as argument, so that it can receive multiple arguments. You then use unpack(arg) to pass these onto the hooked function. While this is very nice style-wise, the use of the ellipsis itself generates garbage, and therefore might bias your statistics. Consider replacing it with something like say 20 static arguments, such as: "return function(a1, a2, a3, a4, etc.)", and then pass a1, a2 etc. to the hooked function. It will look ugly but eliminates garbage generation. 2) You are using the Class:Method syntax to enter functions to watch that are elements of a table. I suggest (and hope) that you use the Class.Method syntax instead. Although the choice is arbitrary from the entry point of view, it ties in better with the Lua concepts of elements of a table (Also see point 3). I know that usually the way to call most methods of XML objects is via the Class:Method syntax (e.g. GameTooltip:Show()), but in Lua, the colon is really nothing special, it's just a shorthand for Class.Method(Class, ...). In otherwords, "GameTooltip:Show() = GameTooltip.Show(GameTooltip)". Also, if you are trying to hook a function, you would specify GameTooltip.Show as the function to hook and not GameTooltip:Show. 3) Do you think you will support functions that are more than one layer deep in a table? For example Class.Subclass.Function? I don't know if you are familiar with the Sea library, but if you need some inspiration on how to do something like this, Sea has two functions Sea.util.getValue and Sea.util.setValue. Those work like getglobal/setglobal, but allow table elements as their arguments too. Their code might be a useful starting point. 4) I don't know if you noticed this, but unfortunately due to the way Blizzard coded things, you can't enumerate the native methods of tables that are representing XML-defined objects. You only have access to methods if you know their name exactly. In other words the following code snippet, Code:
for k, v in GameTooltip do -- do something with k and v end Apart from the above comments, let me again say that you have a great AddOn here that I am going to be using from now on! |
|
07-16-05, 07:15 AM | #23 | |||||
local r = { info.orig_f(unpack(arg)) } to pick up a dynamic number of function return values. This severely skewed the GC results though so I used the ugly and semi-unreliable code local a,b,c,d,e = info.orig_f(unpack(arg)) to reduce garbage generation. You really think it's a good idea to limit the number of arguments a function takes? I convinced myself that 5 return results is unlikely to break things, but I'm not sure what to use as the upper limit to the number of arguments. You think 20 is ok?
where Kaelten asked for method call tracing on particular instances. After I thought about that, I realized I made the mistake you point out. I've decided to use "class.method" syntax to trace functions in a table (works for class methods and package namespaces) and "object:method" syntax to trace method calls on specific objects.
Are you sure Bliz isn't using Lua metatables? I could automatically search __index if it's a table. If __index is a function or if Bliz is using non-Lua method dispatch then I'm pretty much hosed. I'm past the Lua-newbie phase, but I'm not an expert yet... If you have any advice on OO and/or metatables I'd love to hear it. One of the things that I've sketched out for v1.4 is a more robust way of entering the functions to trace. People (especially gamers without Lua experience) are making mistakes entering the function name patterns. I'm planning on having a GUI to build the table and function patterns with check boxes to turn them on and off. I could probably solve the "secret" method problem by including a built-in list of method names. (I'd rather follow __index up to the superclass if I can do that reliably though.) |
||||||
07-17-05, 08:18 PM | #24 | |||||
http://www.wowwiki.com/Widget_API So as you have suggested (and as Iriel has suggested to me in a thread on the WoW forums), you can build a list of these functions, and match any regexp patterns against such a list. The difficulty unfortunately lies in determining what type of UI object a particular Lua table corresponds to, in other words what set of methods it has. There is no good way that I know of to do this For example, given the name SomeRandomFrame, there is no known way to tell that the global Lua table called "SomeRandomFrame" is attached to a UI element of type Frame, Button or something else.
|
||||||
07-17-05, 08:37 PM | #25 | ||
The "foo:bar" syntax uses "foo" as the name of an object, then fetches the metatable info to find the object class. The trace function is inserted into the class table, but stats are only collected if the object instance matches "foo" at call time. I'm not sure I'm explaining it well. (And maybe I misinterpreted Kaelten's original request...)
(BTW, cedar's half up! woot! gonna be nice to trade the hammer for a keyboard and get back to coding... |
|||
07-17-05, 10:09 PM | #26 |
no littlejohn it sounds like you got me right.
It would be nice if I Could track just x instance of whatever class. And it is kinda odd that in Lua OO is basically a very nasty table hack. (Scary in fact) This does allow for some things that other OO languages would just choke on though.
__________________
WowAce.com & CurseForge.com Adminstrator Developer of Ace3, OneBag3, and many other addons and libraries Project lead and Mac developer for the Curse Client Anyone that needs what they want And doesn't want what they need I want nothing to do with |
|
07-17-05, 10:13 PM | #27 |
if you did support nesting, watch out for circular references. They probably aren't extremely common but they do happen.
__________________
WowAce.com & CurseForge.com Adminstrator Developer of Ace3, OneBag3, and many other addons and libraries Project lead and Mac developer for the Curse Client Anyone that needs what they want And doesn't want what they need I want nothing to do with |
|
07-18-05, 12:03 PM | #28 |
ha ha! It is possible to hook getmetatable(foo)[__index] and trace built-in (and inherited) WoW routines on any frame object.
I tried using a proxy table with __index and __newindex methods that just forward to the original table, but that kept crashing WoW for some reason. Maybe lua doesn't like recursive metatable lookup? Anyways, WoW uses the same metatable (and therefore the same __index) on many (all?) XML frame objects. I hooked __index and collected trace history on DEFAULT_CHAT_FRAME. It's possible to dynamically trace an object -- using __index you can see when a new function is called and then it can be dynamically added to the trace. This is probably not that useful to mod authors though. The only thing that seems really cool is automatic generation of the frame XML APIs. (Where did the WoW wiki docs come from anyways?) Legorol: What did you have in mind for this feature? Do you really want to be able to trace, for example, DEFAULT_CHAT_FRAME:* and have all the built-in methods show up? Kaelten: I was hoping I understood you right. I don't think of OO in Lua as a nasty table hack -- I'd call it an elegant table hack. It's like a Python+Scheme love child. Or an alternate universe version of Perl created by a computer scientist instead of a linguist. |
|
07-18-05, 06:43 PM | #29 |
I agree that hooking into the __index function is a good way to see method calls at run time, and can make tracing based on patterns work. I presume what you had in mind is that if the user has specified a regexp, then you don't hook there and then, but if you notice a method call that matches the regexp, then you hook it. That would work and in fact sounds like a good idea for being able to use regexp patterns with XML-generated tables. The particular example I was thinking of is specifying a trace pattern such as GameTooltip%.Set.+ (i mean to indicate that the first '.' is not special but the second one is, i don't know what's the best way for you to handle this).
Unfortunately hooking __index will not help with scanning for the API, because it would require you to actually run WoW and wait for all sorts of method calls to actually happen for you to be able to see that they exist. There are some methods that are in fact never called from any of the default Blizzard UI files, and therefore would be missed, even if you made use of every UI element. One such example is the FontString:SetJustifyV method. The list on the Wiki is generated by a very crude and simple method: scan WoW.exe for all strings and make a list out if, which forms the list of candidates. Then test each object type and see if it has a method that is named any of those candidates. The key here is that testing for a superset that includes stuff other than valid method names is not a problem as long as your set is guaranteed to include all actual methods. OO Supporting OO concepts in TraceEvent is going to be tricky in my opinion. Although there are one or two 'standard' text-book ways of doing OO (classes and instances) in Lua using tables, there are actually a number of possible ways of implementing OO or semi-OO concepts. I have seen different AddOns use very different means to implement OO concepts such as classes and instanciation. Catering for all these scenarios will be difficult, because you won't know in what particular way is an AddOn making use of metatables for example. This is just my opinion, but I beleive that you should drop the ':' syntax alltogether and not try to cater for OO concepts at all. Instead, make sure you have a firm method of tracing table elements, using the '.' syntax. That should be sufficient for those using OO concepts, because they can either specify the table representing the class, or the table representing an instance if they wish. This is just my personal opinion though. Last edited by Legorol : 07-18-05 at 06:45 PM. |
|
08-29-06, 10:34 AM | #30 |
Hmm... sorry for putting this here, but I simply can't get your TraceEvent thingy to work. It shows up fine and spiffy, I just can not seem to add stuff to trace (input field seems to be disabled - it's not accepting any input anyhow, nor can I use direct calls to TraceEvent_AddTrace to get around it).
I have tried to do TraceEventAddName:SetText("A") and nothing whatsoever happens. Is there any way I can easily detect if an addon (I run numerous) can interfere with it? ( <honks at Legorol> ) Sarf |
|
09-05-06, 09:56 PM | #31 |
I have exactly the same issue as Sarf.
I suspect we are both using Cosmos though have no idea whether that is the issue or not. |
|
WoWInterface » Developer Discussions » Dev Tools » TraceEvent - Dynamic Lua code profiling |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|