Thread Tools Display Modes
11-30-05, 03:02 PM   #41
Gello
A Molten Giant
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 521
Testing method:

1. First, Interface, WTF and WTB were deleted and the game logged in and out twice.
2. Next, these two addons were added into the AddOns folder:

Code:
AMemTest.toc
## Interface: 1800
## Title: AMemTest
AMemTest.xml

AMemTest.xml
<Ui>
	<Frame name="AMemTestFrame">
		<Scripts>
			<OnLoad>
				MemTestInfo = {}
				table.insert(MemTestInfo,"GetTime()="..GetTime().." gcinfo="..gcinfo())
				this:RegisterEvent("ADDON_LOADED")
				this:RegisterEvent("PLAYER_ENTERING_WORLD")
			</OnLoad>
			<OnEvent>
				if event=="ADDON_LOADED" then
					table.insert(MemTestInfo,"ADDON_LOADED "..(arg1 or "nil").." GetTime()="..GetTime().." gcinfo="..gcinfo())
				else
					table.insert(MemTestInfo,"PLAYER_ENTERING_WORLD GetTime()="..GetTime().." gcinfo="..gcinfo())
					local i
					for i=1,table.getn(MemTestInfo) do
						DEFAULT_CHAT_FRAME:AddMessage(MemTestInfo[i])
					end
				end
			</OnEvent>
		</Scripts>
	</Frame>
</Ui>
<!-- information was put into a table since methods to frames are known to be slow -->
Code:
ZeLast.toc
## Interface: 1800
## Title: ZeLast
## Notes: Ze Last mod loaded
ZeLast.xml

ZeLast.xml
<Ui>
	<Frame name="ZeLastFrame"/>
</Ui>
<!-- Named ZeLast since it will be assured to be the last addon loaded -->
AddOns load alphabetically. So AMemTest will run first and ZeLast will run last.

3. Then an offline script was made to create the lua's for two test mods:

Code:
test_runs = 1000

-- create TestProcedural.lua that defines a ton of global variables
f = io.open("TestProcedural.lua","w")
for i=1,test_runs do
f:write("Test_Variable"..i.." = "..i.."\n")
end
f:close()

-- create TestOO.lua that defines a table containing a ton of global variables
f = io.open("TestOO.lua","w")
f:write("Test = {\n")
for i=1,test_runs do
f:write("Variable"..i.." = "..i..",\n")
end
f:write("}")
f:close()
The tocs to the two tests:

Code:
## Interface: 1800
## Title: TestOO
## Notes: Loads a ton of stuff into a table
TestOO.lua

## Interface: 1800
## Title: TestProcedural
## Notes: Loads a ton of stuff as global variables
TestProcedural.lua
The test_run above was run for 1k and then 100k.

4. A baseline was run with just AMemTest and ZeLast in the addon folder (with blizzard's stuff):

Only AMemTest and ZeLast in AddOn folder:
GetTime()=18118.791 gcinfo=8888
ADDON_LOADED AMemTest GetTime()=18118.791 gcinfo=8889
ADDON_LOADED ZeLast GetTime()=18118.792 gcinfo=8889
PLAYER_ENTERING_WORLD GetTime()=18128.559 gcinfo=8518
Time to log in: 9.768 (not the true login time but repeatable benchmarks)

We know that a garbage collection happens after addons are done loading and the above seems to confirm this. Let's use the memory at PLAYER_ENTERING_WORLD as a baseline memory. And the time when the process starts as our baseline time.

5. Then I moved these addons in one at a time, exiting completely between tests:

(Bold stuff below is calculated on a calculator after the fact--I should've had the mod calculate it in retrospect)

TestProcedural with the 1k variables:
GetTime()=18264.942 gcinfo=8888
ADDON_LOADED TestProcedural GetTime()=18265.949 gcinfo=9024
ADDON_LOADED ZeLast GetTime()=18265.95 gcinfo=9024
PLAYER_ENTERING_WORLD GetTime()=18274.564 gcinfo=8551
Time to log in: 9.622 seconds
Added memory: 33

TestOO with the 1k variables in a table:
GetTime()=18348.956 gcinfo=8888
ADDON_LOADED AMemTest GetTime()=18348.956 gcinfo=8889
ADDON_LOADED TestOO GetTime()=18348.956 gcinfo=9065
ADDON_LOADED ZeLast GetTime()=18348.956 gcinfo=9065
PLAYER_ENTERING_WORLD GetTime()=18356.237 gcinfo=8586
Time to log in: 7.281
Added memory: 68

TestOO with the 100k variables in a table:
GetTime()=18563.997 gcinfo=8888
ADDON_LOADED AMemTest GetTime()=18563.998 gcinfo=8889
ADDON_LOADED TestOO GetTime()=18564.878 gcinfo=22782
ADDON_LOADED ZeLast GetTime()=18564.879 gcinfo=22783
PLAYER_ENTERING_WORLD GetTime()=18572.648 gcinfo=17325
Time to log in: 8.651
Added memory: 8807

TestProcedural with the 100k variables:
GetTime()=18663.823 gcinfo=8888
ADDON_LOADED AMemTest GetTime()=18663.823 gcinfo=8889
ADDON_LOADED TestProcedural GetTime()=18664.813 gcinfo=16524
ADDON_LOADED ZeLast GetTime()=18664.813 gcinfo=16524
PLAYER_ENTERING_WORLD GetTime()=18672.451 gcinfo=16534
Time to log in: 8.628
Added memory: 8016

The tests could afford to be run many times before a conclusion can be made. For the two parameters tracked:

Load time: The small OO loaded 24% faster than the small Procedural, with no real difference in the large versions. (probably due to the time to churn through a 2.7mb lua file)
Memory: The small Procedural used less than half the memory of the small OO. The large Procedural took 9.9% less memory than the large OO. (the number can vary wildly due to the way tables grow)

I would not swear by any of these numbers since the tests should be run many times. And the testing method could be flawed. But the benefits to one over the other don't appear to jump out.

I know I sound like a lunatic going against what all the college professors and programming principles say, but again I liken the WoW UI sandbox to the old days of 640k memory limits with meticulous mallocs and locking/unlocking pages of memory and tightening assembler code for optimum performance. These are small scale projects done as a hobby. Genuine organizational benefits aside, and the important name collision, I don't see any resources saved yet by going OOP.

That's not to say that we should just abandon all OO concepts and splatter a thousand variables into SavedVariables without reason. If Blizzard announced that all mods must be made with OOP starting tommorw we would see a genuine improvement to the average quality of mods due to the structure imposed by OOP. So it's a good thing.

But there doesn't appear to be any harm in doing mods procedurally. (Except load time which could be significantly in favor of OOP) To back up this point are two tests in this thread: the processing time of a local/global/table lookup and the loading of large amounts of data.

I'd be very interested if anyone could quantify actual resource benefits by going OOP. (Tho I guess that should be "standalone OOP" which doesn't really adhere to the true spirit of OOP) The theory is very sound and OOP is a better way to go, but computers are extremely good as matching stray socks in a room full of socks. It's what they were made to do.

Last edited by Gello : 11-30-05 at 03:20 PM.
  Reply With Quote
11-30-05, 04:04 PM   #42
Rowne
A Fallenroot Satyr
 
Rowne's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2005
Posts: 26
Those are only login tests however, as I stated previously, I'm aware that tables have an extra footprint 'on initialization' as I'm aware that an OO AddOn initializes faster. What I'd really like to see is these AddOns running for an hour, possibly more. Only then could we collate what would happen in the average user's environment, rather than hypothesizing from test results. I believe due to the nature of OO, the results there would remain steady, whereas in procedural they'd get erratic. I have my reasons for thinking this but I'd like to see the proof before I say anything further. Would you be willing to run those tests, Gello?

That said, my point wasn't the one you speak of: sure a computer can do that. Sure a computer can run basic even. That doesn't mean that we should write all our programs in basic though. The thing is, I opt for the best system because it provides a better environment, for both my fellow developer and the user. I try to be a good neighbour. I clean up my socks and I don't force anyone else to do it for me. I try to work with the cleanest system there is, regardless of what my PC can do. I don't let myself become complacent. Just because a computer can do all your work for you, my question is: Is that really a responsible attitude? In my personal opinion only, it isn't. That's why I've been trying to raise awareness.

As I've said, both developers and users have seen very real results from our OO experiments, over on the wowace.com forums, users have reported incredible drops in resource usage. Whether it's memory based on a rolling average (as shown by UIMem plus/minus), saved variables or startup times. I don't know whether this is more down the way we code or whether it's because of OO ... I strongly suspect that it's as much one as the other. If we can raise awareness towards good coding habits, everyone will see these kinds of increases, not just the Ace community.

Wrapping up then, do a rolling test if you would, over time. I'm well aware of why the bigger stamp exists but I don't believe it's a realistic view of how processing 'in-game' will work for AddOns. A slightly bigger memory stamp on login obviously doesn't hinder users or they would've told us it did. It also doesn't seem to be that it gets worse as time goes on, as a number of AddOns do. I'm just trying to figure out how much of this is OO versus procedural or how much of this is just the way Ace coders code. This is only in my opinion however and down to the reports we've had on wowace.com.

If those reports are real though (and I genuinely have no reason to doubt them) then one of the above does provide a better environment and I want to discover which it is.

So yeah ... rolling tests would be good. Do some heavy processing too, like information parsing. Try having something read information from a tooltip into a tabled SavedVariables base and then back out. Do it in OO and procedural, then see which clocks up most after an hour. That'd be a real test.

--- Edit ---

And just to note, I am aware that the GC hits on X defined memory and not after a time limit but there are so many variables that come into play when a player is actually gaming versus a simulated test environment that we should really try to emulate that environment as closely as we can for a real result.
__________________
There can only be so many ways of doing things; rope rubs against rope and it causes fire, fire cleanses all. Sadly, the ropes can't be around to appreciate it.

Short: Tolerance FTW?
  Reply With Quote
12-01-05, 11:27 AM   #43
Gello
A Molten Giant
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 521
What tests do you propose? I'm not adverse to running hours of tests. I cast thousands and thousands (and thousands) of controlled heals to determine +crit items didn't work on heals a long time ago. I determined the +shadow damage to mind blast (1.5 cast) was ~45% before blizzard's post through extensive tests.

But I think the tests done already demonstrate that a well-written procedural mod doesn't hurt a UI. So I'm inclined to consider it settled. But if you can think of an exact test I can write it up. And of course anyone else feel free to test. Tests depend on different people able to reproduce the results.

Methods to frames are really slow by the way. While it's fine to do a test that heavily interacts with frames, be prepared to do it without also because the effects of lua--which is very fast--are insignificant when it hits the juggernaut of a :GetScale().
  Reply With Quote
12-13-05, 04:38 PM   #44
Gello
A Molten Giant
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 521
I finished the "OOP" mod I mentioned in this thread. It's here: http://www.wowinterface.com/download...fo.php?id=4406

My observations: This small mod only has two globals in the lua "side". One for the functions/runtime, the other for SavedVariables. It has a single window to configure, which is not anything fancy by my standards. (and I've done enough xml I can usually type out a whole working file without going to the wiki)

With those two global variables created in the lua "side", the mod created over 140 global variables. Without going OOP this mod would've added ~160-180 global variables. This is due to the xml. We can try to use less xml, but in the end we have to strike a balance with design/aesthetics. Mods would be pretty boring if the best simply did nothing.

So I think while OOP is worthwhile it's more of a resource-saver for the mod writer instead of the mod user which is an important distinction someone made on the irc thing today.

I hope to do tests still to determine if there is actually any quantifiable resources saved (for the user) by going OOP. But would welcome others' findings too.
  Reply With Quote
12-13-05, 08:47 PM   #45
Rowne
A Fallenroot Satyr
 
Rowne's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2005
Posts: 26
Well, all this is chopped down by Ace and AceGUI I'd note (by using a base framework to load only one XML set). XML is irrelevant in Ace AddOns and even with a GUI, if AceGUI is used then the XML is minimal at best (I chopped a near 300-line XML file down to 12 lines in FuncBook). If we're talking about Ace then the XML doesn't even come into the equation, other than Ace's XML which is but one AddOn compared to the many which now support it. Hm, so the outcome of this is that OO works better with a framework to lessen the XML load (such as Ace).

What I'd like to try myself next is to run these tests with a purely Ace(D) AddOn with no XML to see how that compares. If OO alone isn't good enough because of the XML overhead then perhaps the methods I've adopted currently are the best ones for the environment. That's really what I was curious about here, how much of it is OO and how much is Ace. The end result seems that OO is one part of a good thing whereas Ace is the other and they go well together.

---Edit---

In case the point on XML isn't clear; XML only generates extra globals through incorrect use. For example, if you were to use AceGUI and then put all elements in a '$parent' system, then I believe only the main element is global and then the '$parent' name elements are subelements withint he global element's environment. So for example ...

BlahFrame
BlahFrameText

This would be two global elements.

BlahFrame
$parentText

This would be one global element of BlahFrame with a subelement of Text inside it. I need to do more research to provide proof to that however.

And with the overall size of XML and the variables within, as I said, Ace and AceGUI cut down on that or make it non-existant.
__________________
There can only be so many ways of doing things; rope rubs against rope and it causes fire, fire cleanses all. Sadly, the ropes can't be around to appreciate it.

Short: Tolerance FTW?

Last edited by Rowne : 12-13-05 at 08:52 PM.
  Reply With Quote
12-13-05, 09:48 PM   #46
Esamynn
Featured Artist
Premium Member
Featured
Join Date: Jan 2005
Posts: 395
Originally Posted by Rowne
In case the point on XML isn't clear; XML only generates extra globals through incorrect use. For example, if you were to use AceGUI and then put all elements in a '$parent' system, then I believe only the main element is global and then the '$parent' name elements are subelements withint he global element's environment. So for example ...

BlahFrame
BlahFrameText

This would be two global elements.

BlahFrame
$parentText

This would be one global element of BlahFrame with a subelement of Text inside it. I need to do more research to provide proof to that however.

And with the overall size of XML and the variables within, as I said, Ace and AceGUI cut down on that or make it non-existant.
Sorry, not so. Take the example below.

Code:
<Frame name="BlahFrame">
	<Frames>
		<Frame name="$parentText"/>
	</Frames>
</Frame>
This xml code would create two global variables in the Lua namespace. BlahFrame and BlahFrameText. Blizzard would have to shift their parsing of the XML over to an OO style for you to get BlahFrame and BlahFrame.Text.

Edit: The same is true of XML templates.

Last edited by Esamynn : 12-13-05 at 09:50 PM. Reason: typos
  Reply With Quote
12-14-05, 05:28 AM   #47
Gello
A Molten Giant
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 521
AceGUI appears to be just templates? It appears to do nothing different with them. Like the mod I mentioned above, 2 globals made on lua "side" and 140+ on the xml "side." 150 for FuncBook in fact:

FuncBook, FuncBookDB, FuncBookFrame, FuncBookFrameClose, FuncBookFrameCloseText, FuncBookFrameEditor, FuncBookFrameEditorScrollBox, FuncBookFrameEditorScrollBoxBarBottom, FuncBookFrameEditorScrollBoxBarCenter, FuncBookFrameEditorScrollBoxBarTop, FuncBookFrameEditorScrollBoxEditBox, FuncBookFrameEditorScrollBoxScrollBar, FuncBookFrameEditorScrollBoxScrollBarScrollDownButton, FuncBookFrameEditorScrollBoxScrollBarScrollUpButton, FuncBookFrameEditorScrollBoxScrollBarThumbTexture, FuncBookFrameEditorScrollBoxScrollChildFrame, FuncBookFrameEditorTitle, FuncBookFrameHeader, FuncBookFrameHeaderBar, FuncBookFrameHeaderTitle, FuncBookFrameMinus, FuncBookFrameMinusText, FuncBookFrameNormalBackdrop, FuncBookFramePages, FuncBookFramePagesButton, FuncBookFramePagesButtonDisabledTexture, FuncBookFramePagesButtonHighlightTexture, FuncBookFramePagesButtonNormalTexture, FuncBookFramePagesButtonPushedTexture, FuncBookFramePagesLabel, FuncBookFramePagesMenu, FuncBookFramePagesMenuLabel, FuncBookFramePagesMenuNormalBackdrop, FuncBookFramePagesMenuRow1, FuncBookFramePagesMenuRow10, FuncBookFramePagesMenuRow10DisabledText, FuncBookFramePagesMenuRow10Highlight, FuncBookFramePagesMenuRow10HighlightText, FuncBookFramePagesMenuRow10NormalText, FuncBookFramePagesMenuRow11, FuncBookFramePagesMenuRow11DisabledText, FuncBookFramePagesMenuRow11Highlight, FuncBookFramePagesMenuRow11HighlightText, FuncBookFramePagesMenuRow11NormalText, FuncBookFramePagesMenuRow12, FuncBookFramePagesMenuRow12DisabledText, FuncBookFramePagesMenuRow12Highlight, FuncBookFramePagesMenuRow12HighlightText, FuncBookFramePagesMenuRow12NormalText, FuncBookFramePagesMenuRow13, FuncBookFramePagesMenuRow13DisabledText, FuncBookFramePagesMenuRow13Highlight, FuncBookFramePagesMenuRow13HighlightText, FuncBookFramePagesMenuRow13NormalText, FuncBookFramePagesMenuRow14, FuncBookFramePagesMenuRow14DisabledText, FuncBookFramePagesMenuRow14Highlight, FuncBookFramePagesMenuRow14HighlightText, FuncBookFramePagesMenuRow14NormalText, FuncBookFramePagesMenuRow15, FuncBookFramePagesMenuRow15DisabledText, FuncBookFramePagesMenuRow15Highlight, FuncBookFramePagesMenuRow15HighlightText, FuncBookFramePagesMenuRow15NormalText, FuncBookFramePagesMenuRow16, FuncBookFramePagesMenuRow16DisabledText, FuncBookFramePagesMenuRow16Highlight, FuncBookFramePagesMenuRow16HighlightText, FuncBookFramePagesMenuRow16NormalText, FuncBookFramePagesMenuRow17, FuncBookFramePagesMenuRow17DisabledText, FuncBookFramePagesMenuRow17Highlight, FuncBookFramePagesMenuRow17HighlightText, FuncBookFramePagesMenuRow17NormalText, FuncBookFramePagesMenuRow18, FuncBookFramePagesMenuRow18DisabledText, FuncBookFramePagesMenuRow18Highlight, FuncBookFramePagesMenuRow18HighlightText, FuncBookFramePagesMenuRow18NormalText, FuncBookFramePagesMenuRow19, FuncBookFramePagesMenuRow19DisabledText, FuncBookFramePagesMenuRow19Highlight, FuncBookFramePagesMenuRow19HighlightText, FuncBookFramePagesMenuRow19NormalText, FuncBookFramePagesMenuRow1DisabledText, FuncBookFramePagesMenuRow1Highlight, FuncBookFramePagesMenuRow1HighlightText, FuncBookFramePagesMenuRow1NormalText, FuncBookFramePagesMenuRow2, FuncBookFramePagesMenuRow20, FuncBookFramePagesMenuRow20DisabledText, FuncBookFramePagesMenuRow20Highlight, FuncBookFramePagesMenuRow20HighlightText, FuncBookFramePagesMenuRow20NormalText, FuncBookFramePagesMenuRow2DisabledText, FuncBookFramePagesMenuRow2Highlight, FuncBookFramePagesMenuRow2HighlightText, FuncBookFramePagesMenuRow2NormalText, FuncBookFramePagesMenuRow3, FuncBookFramePagesMenuRow3DisabledText, FuncBookFramePagesMenuRow3Highlight, FuncBookFramePagesMenuRow3HighlightText, FuncBookFramePagesMenuRow3NormalText, FuncBookFramePagesMenuRow4, FuncBookFramePagesMenuRow4DisabledText, FuncBookFramePagesMenuRow4Highlight, FuncBookFramePagesMenuRow4HighlightText, FuncBookFramePagesMenuRow4NormalText, FuncBookFramePagesMenuRow5, FuncBookFramePagesMenuRow5DisabledText, FuncBookFramePagesMenuRow5Highlight, FuncBookFramePagesMenuRow5HighlightText, FuncBookFramePagesMenuRow5NormalText, FuncBookFramePagesMenuRow6, FuncBookFramePagesMenuRow6DisabledText, FuncBookFramePagesMenuRow6Highlight, FuncBookFramePagesMenuRow6HighlightText, FuncBookFramePagesMenuRow6NormalText, FuncBookFramePagesMenuRow7, FuncBookFramePagesMenuRow7DisabledText, FuncBookFramePagesMenuRow7Highlight, FuncBookFramePagesMenuRow7HighlightText, FuncBookFramePagesMenuRow7NormalText, FuncBookFramePagesMenuRow8, FuncBookFramePagesMenuRow8DisabledText, FuncBookFramePagesMenuRow8Highlight, FuncBookFramePagesMenuRow8HighlightText, FuncBookFramePagesMenuRow8NormalText, FuncBookFramePagesMenuRow9, FuncBookFramePagesMenuRow9DisabledText, FuncBookFramePagesMenuRow9Highlight, FuncBookFramePagesMenuRow9HighlightText, FuncBookFramePagesMenuRow9NormalText, FuncBookFramePagesMenuScrollBox, FuncBookFramePagesMenuScrollBoxBarBottom, FuncBookFramePagesMenuScrollBoxBarCenter, FuncBookFramePagesMenuScrollBoxBarTop, FuncBookFramePagesMenuScrollBoxScrollBar, FuncBookFramePagesMenuScrollBoxScrollBarScrollDownButton, FuncBookFramePagesMenuScrollBoxScrollBarScrollUpButton, FuncBookFramePagesMenuScrollBoxScrollBarThumbTexture, FuncBookFramePagesMenuScrollBoxScrollChildFrame, FuncBookFramePagesMenuSmallBackdrop, FuncBookFramePagesMenuSpacer, FuncBookFramePagesSelection, FuncBookFramePlus, FuncBookFramePlusText, FuncBookFrameRun, FuncBookFrameRunText, FuncBookFrameSmallBackdrop

So with or without Ace, the XML impact to the global namespace will be the same. To me this is not a problem that needs solving, it's just a statement of how things are. There is no problem (for the user) having stuff in the global namespace. The game does it tens of thousands of times.

Last edited by Gello : 12-14-05 at 05:40 AM.
  Reply With Quote
12-14-05, 06:09 AM   #48
Gello
A Molten Giant
AddOn Author - Click to view addons
Join Date: Jan 2005
Posts: 521
I've looked at AceGUI more in depth. It's just templates with support code. Frames aren't reused unless there's an implementation I'm missing.
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » OO initiative.

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off