C 드라이브 용량 중 hiberfil.sys 파일이 생각보다 큰 용량을 차지한다. 최대 절전 모드용 파일인데 데스크탑에서는 삭제해도 큰 문제가 없는 파일이라고 본다. 삭제하는 방법은 아래와 같다.

명령 프롬프트를 관리자 권한으로 실행하고 'powercfg -h off' 라고 입력한다.

출처 : http://liverex.net/709

Jenkins : 재시작하기

해본 것/팁과 정보 2018.04.19 00:00 posted by 이밋

웹페이지에서 Jenkins 를 재기동하고 싶을 때는 아래 url 을 이용하면 된다.

(jenkins_url)/safeRestart - Allows all running jobs to complete. New jobs will remain in the queue to run after the restart is complete. 

(jenkins_url)/restart - Forces a restart without waiting for builds to complete.

출처 : https://stackoverflow.com/questions/8072700/how-to-restart-jenkins-manually

P.S. 참고로 'safe restart' Plug-in 을 설치하면 관리 페이지에 'Restart Safely' 버튼이 추가된다.

ruby-runtime 에 초기화 문제가 있어 비활성화 혹은 제거하려고 했는데 초기화가 안되니 관리 목록에 보이지 않아 제거나 비활성화할 수 없었다.

수동으로 비활성화하려면 plug-in 폴더에 disabled 파일을 추가하면 된다고 한다.

출처 : https://wiki.jenkins.io/display/JENKINS/Removing+and+disabling+plugins

base64decode

해본 것/팁과 정보 2018.03.06 00:00 posted by 이밋

e-mail 에 첨부된 파일의 경우 base64 로 인코딩되어 있다. 인코딩된 문자열을 파일로 디코딩하고 싶을 때 아래 웹 페이지를 이용하면 된다.

https://www.base64decode.org/

인코딩된 문자열을 붙여넣고 'DECODE' 버튼을 누르면 디코딩된 파일을 다운받을 수 있다.

CALL :NORMALIZEPATH "..\..\..\foo\bar.txt"
SET BLAH=%RETVAL%

ECHO "%BLAH%"

:: ========== FUNCTIONS ==========
EXIT /B

:NORMALIZEPATH
  SET RETVAL=%~dpfn1
  EXIT /B

출처 : https://stackoverflow.com/questions/1645843/resolve-absolute-path-from-relative-path-and-or-file-name

UE4 : BootstrapPackagedGame

해본 것/팁과 정보 2017.11.08 00:00 posted by 이밋

언리얼로 패키징하면 최상위 폴더에 게임 exe 파일을 실행해주는 exe 파일이 생성된다. 확인해보니 패키징 과정 중 WinPlatform.Automain.cs 에 있는 StageBootstrapExecutable 에 의해 생성되고 있었다. 

다음과 같은 과정을 거쳐 생성된다.

: Engine/Binaries/[Platform]/BootstrapPackagedGame-[Platform]-Shipping.exe 파일을 타겟 경로에 복사
: Build/Windows/Application.ico 파일을 101 리소스 갱신
: 201 리소스 아이디로 실행할 게임 exe 파일 상대 경로 문자열 갱신
: 301 리소스 아이디로 실행할 게임 기본 파라미터 문자열 갱신

BootstrapPackagedGame 은 2가지 기능은 한다.

: MSVCP140.DLL 과 XINPUT1_3.DLL 을 체크하여 Microsoft Visual C++ 2015 Runtime 이나 DirectX Runtime 이 설치되었는지 확인한다.
: 설치되어 있지 않다면 배포 버전에 포함된 UE4PrereqSetup_x64.exe 를 실행한다.
: 필요한 패키지들이 설치되어 있다면 리소스 경로를 참고하여 게임 exe 를 실행한다.

실행 중인 OS가 64 비트인지 확인하기 위해서는 IsWow64Process 를 이용하면 된다. 지원하지 않는 OS 도 있으니 GetProcAddress 를 이용해야한다. 64 비트 프로그램의 경우에는 그냥 TRUE 를 return 하면 된다.

typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);

LPFN_ISWOW64PROCESS fnIsWow64Process;

BOOL IsWow64()
{
#ifdef _WIN64
    return TRUE;
#else
    BOOL bIsWow64 = FALSE;

    //IsWow64Process is not available on all supported versions of Windows.
    //Use GetModuleHandle to get a handle to the DLL that contains the function
    //and GetProcAddress to get a pointer to the function if available.

    fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
GetModuleHandle(TEXT("kernel32")),"IsWow64Process");
    if (NULL != fnIsWow64Process)
    {
        if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
        {
            //handle error
        }
    }
    return bIsWow64;
#endif
}

참고 : https://msdn.microsoft.com/ko-kr/library/windows/desktop/ms684139(v=vs.85).aspx

디버그 모드에서는 링크 문제가 없는데 릴리즈 모드에서 링크 에러가 발생했다. 해당 라이브러리를 쓰는 다른 프로젝트는 문제가 없어서 lib 경로 문제인가 싶어서 이리저리 확인해 봤으나 원인을 찾을 수가 없었다. lib 에 정말 symbol 이 있는지 확인해 보고 싶어졌다. 

Visual Studio 에 포함된 dumpbin 을 이용하면 된다.

dumpbin /symbols [lib 파일명]

Visual Studio 에 포함된 libcmt.lib 를 까보면 이런 식으로 보인다.

dumpbin /symbols libcmt.lib


File Type: LIBRARY


COFF SYMBOL TABLE000 00C7A09E ABS    notype       Static       | @comp.id
001 00000011 ABS    notype       Static       | @feat.00
002 00000000 UNDEF  notype       External     | _strcat003 00000000 UNDEF  notype       WeakExternal | __mbscat

    Default index        2 Alias record

String Table Size = 0x0 bytes

COFF SYMBOL TABLE
000 00C7A09E ABS    notype       Static       | @comp.id
001 00000011 ABS    notype       Static       | @feat.00
002 00000000 UNDEF  notype       External     | _strcpy
003 00000000 UNDEF  notype       WeakExternal | __mbscpy

    Default index        2 Alias record

String Table Size = 0x0 bytes

COFF SYMBOL TABLE
000 00C7A09E ABS    notype       Static       | @comp.id
001 00000011 ABS    notype       Static       | @feat.00

...(생략)

0A4 00000000 SECT33 notype       External     | ??_C@_01EEMJAFIK@?6?$AA@ (`string')
0A5 00000000 SECT34 notype       Static       | .rdata    Section length    3, #relocs    0, #linenums    0, checksum BB71EC38, selection    2 (pick any)

0A7 00000000 SECT34 notype       External     | ??_C@_02LLMPMKNF@?$DO?5?$AA@ (`string')

0A8 00000000 SECT35 notype       Static       | .rdata

    Section length    9, #relocs    0, #linenums    0, checksum F5F13728, selection    2 (pick any)

0AA 00000000 SECT35 notype       External     | ??_C@_08OMAHNMHJ@?6Data?3?5?$DM?$AA@ (`string')

0AB 00000000 SECT36 notype       Static       | .rdata
    Section length   2A, #relocs    0, #linenums    0, checksum 21F15550, selection    2 (pick any)

0AD 00000000 SECT36 notype       External     | ??_C@_0CK@DKGBICFE@?6Allocation?5number?5within?5this?5f@ (`string')

0AE 00000000 SECT37 notype       Static       | .rdata

    Section length    8, #relocs    0, #linenums    0, checksum AFE40ACB, selection    2 (pick any)

0B0 00000000 SECT37 notype       External     | ??_C@_07DFDJCKFN@?6Size?3?5?$AA@ (`string')
0B1 00000000 SECT38 notype       Static       | .rdata

    Section length    D, #relocs    0, #linenums    0, checksum 37DE352B, selection    2 (pick any)
0B3 00000000 SECT38 notype       External     | ??_C@_0N@MHFFIMFG@?6Address?3?50x?$AA@ (`string')

0B4 00000000 SECT39 notype       Static       | .rdata
    Section length   48, #relocs    0, #linenums    0, checksum DB7219C5, selection    2 (pick any)

0B6 00000000 SECT39 notype       External     | ??_C@_0EI@CLEPFNGI@Stack?5area?5around?5_alloca?5memory@ (`string')
0B7 00000000 SECT3A notype       Static       | .rdata

    Section length   1A, #relocs    0, #linenums    0, checksum B3C0476C, selection    2 (pick any)
0B9 00000000 SECT3A notype       External     | ??_C@_0BK@ODNDAGKB@?$CFs?$CFs?$CFp?$CFs?$CFzd?$CFs?$CFd?$CFs?$CFs?$CFs?$CFs?$CFs?$AA@ (`string')

0BA 00000000 SECT3B notype       Static       | .rdata
    Section length   34, #relocs    0, #linenums    0, checksum D4450C50, selection    2 (pick any)
0BC 00000000 SECT3B notype       External     | ??_C@_0DE@OHJBPMBP@A?5variable?5is?5being?5used?5without@ (`string')

0BD 00000000 UNDEF  notype       External     | ___security_cookie
0BE 00000000 SECT3C notype       Static       | .sxdata


...(생략)


  Summary


           4 .00cfg
           4 .CRT$XCA
          10 .CRT$XCAA
           4 .CRT$XCZ
           4 .CRT$XDA
           4 .CRT$XDZ
           4 .CRT$XIA
          10 .CRT$XIAA
          10 .CRT$XIAC
           8 .CRT$XIC
           4 .CRT$XIZ
           4 .CRT$XLA
           4 .CRT$XLC
           4 .CRT$XLD
           4 .CRT$XLZ
           4 .CRT$XPA
           4 .CRT$XPZ
           4 .CRT$XTA
           4 .CRT$XTZ
         3A9 .bss
          38 .data
          77 .data$r
         1D0 .debug$F
       A7880 .debug$S
        3454 .debug$T
         5BF .drectve
          AC .gfids$y
        742E .rdata
          18 .rdata$T
         120 .rdata$r
           4 .rtc$IAA
           4 .rtc$IZZ
           4 .rtc$TAA
           4 .rtc$TZZ
          3C .sxdata
       1B0E8 .text$mn
           F .text$mn$00
          1B .text$x
           1 .tls
          8C .tls$
           1 .tls$ZZZ
         2E0 .xdata$x
       6C630 _RDATA


0BC 00000000 SECT3B notype       External     | ??_C@_0DE@OHJBPMBP@A?5variable?5is?5being?5used?5without@ (`string')

위와 같이 External 이 표기된 부분을 디버그와 릴리즈 모드를 비교해봤더니 릴리즈 모드에서 링크에러가 발생한 symbol을 찾을 수 없었다.

문제가 생긴 함수는 constructor 였는데 명시적으로 구현을 안해서 그런건지 릴리즈에서만 링크 에러가 발생한 것이었다. 다행히 명시적으로 cpp 파일에 구현해주니 링크 에러는 해결되었다.

참고 : https://stackoverflow.com/questions/305287/how-to-see-the-contents-of-windows-library-lib

이펙트 파티클을 일정 기간 생성된 상태로 초기화하고 싶을 때 Warmup Time 을 설정하게 된다.

UParticleSystemComponent::ActivateSystem 코드를 보면 어떻게 동작하는지 알 수 있는데  WarmupTime을 WarmupTickRate 나눈 수만큼 TickComponent 를 호출하는 식이다.

if (WarmupTime != 0.0f)
{
bool bSaveSkipUpdate = bSkipUpdateDynamicDataDuringTick;
bSkipUpdateDynamicDataDuringTick = true;
bWarmingUp = true;
ResetBurstLists();


float WarmupElapsed = 0.f;
float WarmupTimestep = 0.032f;

if (WarmupTickRate > 0)
{
WarmupTimestep = (WarmupTickRate <= WarmupTime) ? WarmupTickRate : WarmupTime;
}

while (WarmupElapsed < WarmupTime)
{
TickComponent(WarmupTimestep, LEVELTICK_All, NULL);
WarmupElapsed += WarmupTimestep;
}

bWarmingUp = false;
WarmupTime = 0.0f;
}

예를 들어 WarmupTime 을 100 WarmupTickRate 를 0 으로 설정한 경우 100 / 0.032(WarmupTickRate 기본값) = 3125 Tick 을 돌아서 이 이펙트가 스폰될 때 마다 i7 + Nvidia 970 + 32GB Mem 정도 사양에서도 버벅이는 것을 느낄 수 있다. 초당 0.7 정도의 8개 짜리 스프라이트 이펙트였는데 스프라이트 파티클 개수가 10000개에 육박한 것을 볼 수 있었다. :(

언리얼에서 스크린샷이나 다른 이유로 랙이 걸릴 때 마다 다른 PC 에 비해 World::TimeSeconds 가 느리게 가는 현상이 발견되었다.

확인해보니 AWorldSettings::FixupDeltaSeconds 에 의해 제한되고 있었다.

float AWorldSettings::FixupDeltaSeconds(float DeltaSeconds, float RealDeltaSeconds)

{

// DeltaSeconds is assumed to be fully dilated at this time, so we will dilate the clamp range as well

float const Dilation = GetEffectiveTimeDilation();

float const MinFrameTime = MinUndilatedFrameTime * Dilation;

float const MaxFrameTime = MaxUndilatedFrameTime * Dilation;


// clamp frame time according to desired limits

return FMath::Clamp(DeltaSeconds, MinFrameTime, MaxFrameTime);

}

WorldSettings 의 MinUndilatedFrameTime 과 MaxUndilatedFrameTime 에 설정할 수 있었다.


기본 값은 BaseGame.ini 에 설정되어 있다.

[/Script/Engine.WorldSettings]

MinUndilatedFrameTime=0.0005 ; 2000 fps

MaxUndilatedFrameTime=0.4 ; 2.5 fps

0.4초 이상은 버려지니 스크린샷으로 2~3초가 지났어도 World 는 0.4초 밖에 안 지난 것으로 취급되는 상황이었다.

P2P 마스터를 지원하는 상황에서는 DefaultGame.ini 에 MaxUndilatedFrameTime 을 충분히 큰 값으로 올려주고 그 값을 넘어가는 오차가 발생하면 자르거나 재동기화하는 식으로 구현하는게 좋을 것 같다.