? 欧美放荡办公室videos,精品国产乱码久久久久久紫薇蜜桃,果冻传媒九一制片厂在线观
聯(lián)系我們

給我們留言

聯(lián)系我們

地址:福建省晉江市青陽街道洪山路國際工業(yè)設(shè)計(jì)園納金網(wǎng)

郵箱:info@narkii.com

電話:0595-82682267

(周一到周五, 周六周日休息)

當(dāng)前位置:主頁 > 3D教程 > 圖文教程

UnrealEngine4使用反匯編來確定該進(jìn)行優(yōu)化的地方

來源: 52vr | 責(zé)任編輯:傳說的落葉 | 發(fā)布時(shí)間: 2019-06-13 08:38 | 瀏覽量:

Unreal Engine 4 —— 使用反匯編來確定該進(jìn)行優(yōu)化的地方

 
這篇文章翻譯自Robert Troughton的博客Using the Disassembler to Highlight Optimization Targets,已征得原作者同意。
 
This post is translated from English. You can find the original English language version here: http://coconutlizard.co.uk/blog/ue4/using-the-disassembler/
 
UE4中有很多的字符串處理的函數(shù),這些函數(shù)會在UE4中的各種情況下被調(diào)用 —— 例如無論在編輯器、cooking或者運(yùn)行游戲時(shí),都會有一大堆的字符串函數(shù)被調(diào)用。
 
在最近的測試中,我們著重測試了一下FPaths::IsRelative()函數(shù),這個(gè)函數(shù)可以在Paths.cpp中被找到:
 

[代碼]:

1 bool FPaths::IsRelative(const FString& InPath)
2 {
3   const bool IsRooted = InPath.StartsWith(TEXT("\\"), ESearchCase::CaseSensitive)   ||
4               InPath.StartsWith(TEXT("/"), ESearchCase::CaseSensitive)  ||
5               InPath.StartsWith(TEXT("root:/")) |
6               (InPath.Len() >= 2 && FChar::IsAlpha(InPath[0]) && InPath[1] == TEXT(':'));
7   return !IsRooted;
8 }
 
以上的代碼看起來是無害的,只是一些很普通的字符串測試來判定InPath是相對路徑(eg. “../engine/myfile.uasset”) 還是絕對路徑 (eg. “c:\myfile.uasset”)。
 
為了研究這段代碼,我啟動Debugger,在函數(shù)中設(shè)置了斷點(diǎn)并且查看其匯編代碼。此時(shí)發(fā)生了非??植赖氖?,以下只是匯編代碼中的一小段:
 

[代碼]:

01 00007FF6DFF97B4E  mov         ecx,2 
02 00007FF6DFF97B53  xor         edi,edi 
03 00007FF6DFF97B55  xor         edx,edx 
04 00007FF6DFF97B57  mov         r8d,ecx 
05 00007FF6DFF97B5A  mov         qword ptr [rsp+70h],rbx 
06 00007FF6DFF97B5F  mov         dword ptr [rbp+28h],edi 
07 00007FF6DFF97B62  mov         qword ptr [rbp-10h],rdi 
08 00007FF6DFF97B66  mov         qword ptr [rbp-8],2 
09 00007FF6DFF97B6E  call        DefaultCalculateSlack (07FF6DFEC7DD0h) 
10 00007FF6DFF97B73  movsxd      rcx,eax 
11 00007FF6DFF97B76  mov         rax,qword ptr [rbp-10h] 
12 00007FF6DFF97B7A  mov         dword ptr [rbp-4],ecx 
13 00007FF6DFF97B7D  test        rax,rax 
14 00007FF6DFF97B80  jne         FPaths::IsRelative+46h (07FF6DFF97B86h) 
15 00007FF6DFF97B82  test        ecx,ecx 
16 00007FF6DFF97B84  je          FPaths::IsRelative+5Bh (07FF6DFF97B9Bh) 
17 00007FF6DFF97B86  mov         rdx,rcx 
18 00007FF6DFF97B89  xor         r8d,r8d 
19 00007FF6DFF97B8C  mov         rcx,rax 
20 00007FF6DFF97B8F  add         rdx,rdx 
21 00007FF6DFF97B92  call        FMemory::Realloc (07FF6DFF04CB0h) 
22 00007FF6DFF97B97  mov         qword ptr [rbp-10h],rax 
23 00007FF6DFF97B9B  lea         rdx,[ToUpperAdjustmentTable+2ABCh (07FF6E1EFFB9Ch)] 
24 00007FF6DFF97BA2  mov         r8d,4 
25 00007FF6DFF97BA8  mov         rcx,rax 
26 00007FF6DFF97BAB  call        FGenericPlatformString::Memcpy (07FF6DFED3CA0h) 
27 00007FF6DFF97BB0  lea         rdx,[rbp-10h] 
28 00007FF6DFF97BB4  xor         r8d,r8d 
29 00007FF6DFF97BB7  mov         rcx,rsi 
30 00007FF6DFF97BBA  mov         ebx,1 
31 00007FF6DFF97BBF  call        FString::StartsWith (07FF6DFEDD440h) 
32 00007FF6DFF97BC4  test        al,al 
33 00007FF6DFF97BC6  jne         FPaths::IsRelative+1BBh (07FF6DFF97CFBh)
 
以上僅僅是整個(gè)函數(shù)的匯編代碼的冰山一角,而整個(gè)函數(shù)也只有一行cpp代碼,這簡直是恐怖。
 
此外,這個(gè)代碼不僅僅只是長而已,你應(yīng)該可以看到有FMemory::Realloc()函數(shù)的調(diào)用。在整個(gè)匯編代碼中,F(xiàn)Memory::Realloc()函數(shù)調(diào)用了3次。與之對應(yīng)的,F(xiàn)Memory::Free()函數(shù)也出現(xiàn)了多次。
 
還有,StartsWith()函數(shù)也不是一個(gè)很便宜的函數(shù)(注意StartsWith()只有一個(gè)關(guān)于FString的Implementation)。
 
因此,我做了如下事:
 
減少了StartsWith()函數(shù)的調(diào)用,轉(zhuǎn)而使用更為直接的字符比較。
移除了runtime的TEXT()區(qū)塊,取而代之的是在外部直接創(chuàng)建。
將其中RootPrefix測試設(shè)為在編輯器中才有效。
因此,我最終的代碼如下:
 

[代碼]:

01 // Paths.cpp
02  
03     #if WITH_EDITOR
04     FString FPaths::RootPrefix = TEXT("root:/");
05     #endif // WITH_EDITOR
06     bool FPaths::IsRelative(const FString& InPath)
07     {
08       const uint32 PathLen = InPath.Len();
09       const bool IsRooted = PathLen &&
10         ((InPath[0] == '/') ||
11           (PathLen >= 2 && (
12             ((InPath[0] == '\\') && (InPath[1] == '\\'))
13             || (InPath[1] == ':' && FChar::IsAlpha(InPath[0]))
14     #if WITH_EDITOR
15             || (InPath.StartsWith(RootPrefix))
16     #endif // WITH_EDITOR
17           ))
18         );
19       return !IsRooted;
20     }
 
對于.h文件,添加內(nèi)容如下:
 

[代碼]:

1 // Paths.h
2     private:
3     #if WITH_EDITOR
4       static FString RootPrefix;
5     #endif // WITH_EDITOR
 
重新編譯后,最終的匯編代碼如下:
 

[代碼]:

01 00007FF7147B695A  mov         edx,dword ptr [r8+8] 
02 00007FF7147B695E  mov         rsi,rcx 
03 00007FF7147B6961  test        edx,edx 
04 00007FF7147B6963  je          FPaths::ConvertRelativePathToFull+67h (07FF7147B6997h) 
05 00007FF7147B6965  dec         edx 
06 00007FF7147B6967  je          FPaths::ConvertRelativePathToFull+67h (07FF7147B6997h) 
07 00007FF7147B6969  mov         rax,qword ptr [r8] 
08 00007FF7147B696C  movzx       ecx,word ptr [rax] 
09 00007FF7147B696F  cmp         cx,2Fh 
10 00007FF7147B6973  je          FPaths::ConvertRelativePathToFull+0A9h (07FF7147B69D9h) 
11 00007FF7147B6975  cmp         edx,2 
12 00007FF7147B6978  jb          FPaths::ConvertRelativePathToFull+67h (07FF7147B6997h) 
13 00007FF7147B697A  cmp         cx,5Ch 
14 00007FF7147B697E  jne         FPaths::ConvertRelativePathToFull+56h (07FF7147B6986h) 
15 00007FF7147B6980  cmp         word ptr [rax+2],cx 
16 00007FF7147B6984  je          FPaths::ConvertRelativePathToFull+0A9h (07FF7147B69D9h) 
17 00007FF7147B6986  cmp         word ptr [rax+2],3Ah 
18 00007FF7147B698B  jne         FPaths::ConvertRelativePathToFull+67h (07FF7147B6997h) 
19 00007FF7147B698D  call        qword ptr [__imp_iswalpha (07FF716557B48h)] 
20 00007FF7147B6993  test        eax,eax 
21 00007FF7147B6995  jne         FPaths::ConvertRelativePathToFull+0A9h (07FF7147B69D9h)
 
以上的匯編代碼是在non-editor模式中的整個(gè)函數(shù)的匯編代碼,我相信你我都能同意以上代碼的性能要好得多。
 
優(yōu)化這段代碼還帶來了一個(gè)很好的副作用:編譯器會將這段邏輯進(jìn)行inline操作,我們甚至不需要聲明FORCEINLINE或者INLINE宏!
 
我的最終測試表明這段代碼的性能快了將近20倍,而代碼資源占用量只是原來的10%。

相關(guān)文章
網(wǎng)友評論

您需要登錄后才可以發(fā)帖 登錄 | 立即注冊

關(guān)閉

全部評論:0條

推薦
熱門