0x00 Preamble
This article is not intended to compare for and foreach who are more efficient, not designed for and foreach values, and so on. Simply discussing whether foreach will affect unity3d efficiency.
This is the beginning of things, before looking at Unity optimization, met with such a sentence:
Try not to use foreach, but instead use the for. foreach actually involves the use of iterators, and it is rumored that each iteration of the loop produces a bytes of garbage. Then the Loop 10 times is 240Bytes.
Because of the recent contact with Unity and C #, there was no careful study of the underlying principles, just a simple belief. So I'll try to avoid using foreach in my Code as much as I can, although I think foreach really works.
And then, every time I see a traversal, I think about why foreach has this kind of behavior, and I want to know the real reason why, until today, I went deep into the material to justify this view.
0x01 C # is more streamlined and more efficient than the foreach directive?
On this statement, Baidu (too lazy to turn over the wall to Google), to find a widely forwarded article:
Unity should try to avoid using foreach
The inside code is as follows:
usingUnityengine;usingSystem.Collections; Public classForeachtest:monobehaviour {protectedArrayList M_array;voidStart () {M_array =NewArrayList (); for(inti =0; I <2; i++) M_array. ADD (i); }voidUpdate () { for(inti =0; I < +; i++) {foreach(intEinchM_array) {//big GC alloc!!! do no Use this code!} } for(inti =0; I < +; i++) { for(intK =0; K < M_array. Count; k++) {//no GC alloc!!} } } }
When I first saw the code, I was wondering why a simple foreach would have so much memory overhead. With a puzzled, continue to search, until you see a reply to the answer:
As a script for Unity3d, is the for in C # really more efficient than foreach?
So the doubts here can be answered in almost all:
Each foreach generates 40B of memory, and if you use foreach in a script's update, there will be a 40B GC ALLOC per frame.
I've seen it in another place before. 2014Unity Asian developer Conference on the record there is a saying:
Detects the option to have more than 20B memory allocations per frame
This almost means that using foreach in the update is not a wise choice. about why the memory allocation of more than 20B per frame is not very good, I have not carefully studied, personal guess if each frame 20B, accumulated a period of time there will be a large number of recycled memory accumulation, and mono recovery mechanism in the recovery time point is not fixed, if a longer period of time unified recovery, will inevitably lead to the card phenomenon.
0x02 We don't use foreach?
Before I answer the question, I intend to follow Mr. Wang Jianfei's code to verify that the code is almost consistent with his answer:
usingUnityengine;usingSystem.Collections;usingSystem.Collections.Generic; Public classGctest:monobehaviour {list<int> iList =Newlist<int> ();intCount =Ten;voidAwake () { for(inti =0; I < count; i++) {ilist.add (i); } }// Use this for initialization voidStart () {}//Update is called once per frame voidUpdate () {Testforeach ();//testnoforeach (); //testfor (); //testusing ();}voidTestforeach () {//debug.log ("Testforeach"); foreach(varEinchIList) {//debug.log (e);}//foreach (var e in iList) { //foreach (var item in iList) { ////debug.log (e); // } //}}voidTestnoforeach () {//debug.log ("Testnoforeach"); varE = Ilist.getenumerator (); while(E.movenext ()) {//debug.log (e.current);} }voidTestfor () {//debug.log ("testfor"); for(inti =0; I < count; ++i) {//debug.log (Ilist[i]);} }voidTestusing () {//debug.log ("testusing"); using(varE = Ilist.getenumerator ()) { while(E.movenext ()) {//debug.log (e.current);} }; }}
Note that this is a C # script added directly to the Unity project, using the built-in mono compiler to compile the code.
When I use Testforeach () in the update, the result is as follows:
You can see that in my Win7 + Unity64 environment, foreach does have a 40B GC Alloc.
Then use the comment code in Testforeach ():
foreach (varin iList){ foreach (varin iList){ //Debug.Log(e); } }
A total of 440B memory overhead, which confirms that a foreach generates a 40B heap memory argument.
Then using Testnoforeach () in update, the results are as follows:
You can see no GC Alloc.
The result seems to be saying, don't use foreach!
In retrospect I also said:
* * The truth is there:
In Finally, mono compiles a code that will valuetype the enumerator,boxing process!!
What a waste!!!
This is a bug! of the old version of the Mono compiler in unity. **
Since it is the old version of Mono bug, can you go around?
The answer is yes, because our project is just to put the script into the DLL package and put it into the works. When compiling the script, you are using the latest Ms compiler, is that not a problem?
Test, put the newly compiled DLL into the project, the result is as follows:
The Testforeach () method is also used, but this time there is no GC alloc.
0X03 conclusion?
Believe that the above friends have already had their own ideas.
1. The script is placed directly in the Unity Project, and using foreach is not a big concern if it is not called every frame in the update. If you are in update, and you are using foreach frequently in multiple places, you need to consider it carefully.
2. Script into the DLL, love the ground!
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Unity3d Series 1:foreach has no effect on performance