Warp Cache Optimizasyon

Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.

s1nwar

Üye
Editör
Üye
Mesaj
52
Çözümler
2
Beğeni
367
Puan
374
Ticaret Puanı
0
Merhaba ışınlanma ile ilgili bir düzeltme performans yönünde.

Önce
  • Aynı haritada herhangi bir yere ışınlandığınızda;
  • CPythonNetworkStream::Warp her çağrıldığında Destroy() + Create() + Warp() işlemleri koşulsuz çalışıyordu.
  • Aynı haritada tekrar warp atıldığında bile map tamamen yeniden yükleniyordu.
  • Bu durum gereksiz performans kaybına cpu + i/o, gpu kullanımını arttırıyor.
Sonra
  • Yeni bir g_strCachedMapName eklendi ve son yüklenen map adı cache’leniyor.
  • Warp() çağrısında eğer CurrentMap == CachedMap ise tam reload yapılmıyor.
  • Bunun yerine sadece pozisyon güncelleniyor (Direct reposition).
Böylece aynı haritada yapılan warp işlemleri daha hızlı gerçekleşiyor, ve işlem yükü azalıyor.

Burayı görüntülemek için üye girişi yapmalı veya kayıt olmalısınız.
 
En son bir moderatör tarafından düzenlenmiş:
Paylaşım için teşekkürler. Ama anlamadığım bir şey var; anlatım eksik mi yoksa tam mı?
Çünkü şu anki hali ile teknik olarak bu kodun performansa hiçbir katkısı olmaz.
 
Paylaşım için teşekkürler. Ama anlamadığım bir şey var; anlatım eksik mi yoksa tam mı?
Çünkü şu anki hali ile teknik olarak bu kodun performansa hiçbir katkısı olmaz.
Rica ederim, anlatım tam, neden olmasın anlayamadım? kodu okuyarak yorumlayabilir misiniz?
 
Rica ederim, anlatım tam, neden olmasın anlayamadım? kodu okuyarak yorumlayabilir misiniz?
C++:
Genişlet Daralt Kopyala
    [...]
    if (!g_strCachedMapName.empty() && g_strCachedMapName == strCurrentMap)
    {
        rkNetStream.Warp(nX, nY);
        return Py_BuildNone();
    }

    rkNetStream.Warp(nX, nY);
    [...]
Verilen kodda koşul ne olursa olsun aynı map veya farklı map fark etmeksizin aynı çağrı yapılıyor ve şu kısım çağrılıyor;

C++:
Genişlet Daralt Kopyala
void CPythonNetworkStream::Warp(LONG lGlobalX, LONG lGlobalY)
{
    CPythonBackground& rkBgMgr=CPythonBackground::Instance();
    rkBgMgr.Destroy();
    rkBgMgr.Create();
    rkBgMgr.Warp(lGlobalX, lGlobalY);
    rkBgMgr.RefreshShadowQualityLevel();
    rkBgMgr.RefreshShadowTargetLevel();
    LONG lLocalX = lGlobalX;
    LONG lLocalY = lGlobalY;
    __GlobalPositionToLocalPosition(lLocalX, lLocalY);
    float fHeight = CPythonBackground::Instance().GetHeight(float(lLocalX), float(lLocalY));

    IAbstractApplication& rkApp=IAbstractApplication::GetSingleton();
    rkApp.SetCenterPosition(float(lLocalX), float(lLocalY), fHeight);

    __ShowMapName(lLocalX, lLocalY);
}

if bloğu içindeki rkNetStream.Warp(nX, nY); satırını rkBgMgr.Warp(nX, nY); olarak değiştirmek bir nebze etkili olabilir.
Ancak her halükarda harita yok edildiği için tekrar Create çağrılmak zorunda olacak.

Aşağıdaki gibi olabilir:
C++:
Genişlet Daralt Kopyala
    if (!g_strCachedMapName.empty() && g_strCachedMapName == strCurrentMap)
    {
        rkBgMgr.Create() // < bu olmazsa crash yaşanır
        rkBgMgr.Warp(nX, nY);
        return Py_BuildNone();
    }

Bunun da etkisi ne kadar olur emin değilim, bende psm ekli olduğundan farkı tam olarak ayırt edemiyorum.
 
C++:
Genişlet Daralt Kopyala
    [...]
    if (!g_strCachedMapName.empty() && g_strCachedMapName == strCurrentMap)
    {
        rkNetStream.Warp(nX, nY);
        return Py_BuildNone();
    }

    rkNetStream.Warp(nX, nY);
    [...]
Verilen kodda koşul ne olursa olsun aynı map veya farklı map fark etmeksizin aynı çağrı yapılıyor ve şu kısım çağrılıyor;

C++:
Genişlet Daralt Kopyala
void CPythonNetworkStream::Warp(LONG lGlobalX, LONG lGlobalY)
{
    CPythonBackground& rkBgMgr=CPythonBackground::Instance();
    rkBgMgr.Destroy();
    rkBgMgr.Create();
    rkBgMgr.Warp(lGlobalX, lGlobalY);
    rkBgMgr.RefreshShadowQualityLevel();
    rkBgMgr.RefreshShadowTargetLevel();
    LONG lLocalX = lGlobalX;
    LONG lLocalY = lGlobalY;
    __GlobalPositionToLocalPosition(lLocalX, lLocalY);
    float fHeight = CPythonBackground::Instance().GetHeight(float(lLocalX), float(lLocalY));

    IAbstractApplication& rkApp=IAbstractApplication::GetSingleton();
    rkApp.SetCenterPosition(float(lLocalX), float(lLocalY), fHeight);

    __ShowMapName(lLocalX, lLocalY);
}

if bloğu içindeki rkNetStream.Warp(nX, nY); satırını rkBgMgr.Warp(nX, nY); olarak değiştirmek bir nebze etkili olabilir.
Ancak her halükarda harita yok edildiği için tekrar Create çağrılmak zorunda olacak.

Aşağıdaki gibi olabilir:
C++:
Genişlet Daralt Kopyala
    if (!g_strCachedMapName.empty() && g_strCachedMapName == strCurrentMap)
    {
        rkBgMgr.Create() // < bu olmazsa crash yaşanır
        rkBgMgr.Warp(nX, nY);
        return Py_BuildNone();
    }

Bunun da etkisi ne kadar olur emin değilim, bende psm ekli olduğundan farkı tam olarak ayırt edemiyorum.
Eğer map aynı ise Destroy, create çağırmak bir yüktür crash filan yaşanmıyor test edebilirsiniz, sadece çağrıyı yakalıyor. Map aynı ise x,y olarak gider yeniden destroy edip oluşturma yapmaz sadece map ismi mevcuta göre değiştiğinde destroy ve create çağrılır.

Screenshot_415.webp

Aynı map tekrar çağrıldığında skip durumlarını test ettim. Bir problem yok.
 
gerçek performan istiyorsanız herşeyi g_strCachedMapName bu koşula baglamak gerek benim fikrim yani örnek yeni mapsa islem yükünü al değilse atla gibi
Niye her şeyi bağlayalım ki, çağrı buradan geçiyor fonksiyonlara gitmeden burada yaparsan zaten sonuca ulaşmış oluyorsun, neden uzatalım?
 
Eğer map aynı ise Destroy, create çağırmak bir yüktür crash filan yaşanmıyor test edebilirsiniz, sadece çağrıyı yakalıyor. Map aynı ise x,y olarak gider yeniden destroy edip oluşturma yapmaz sadece map ismi mevcuta göre değiştiğinde destroy ve create çağrılır.

25931 eklentisini görüntüle
Aynı map tekrar çağrıldığında skip durumlarını test ettim. Bir problem yok.
Demek istediğini anlıyorum, zaten kod teoride çalışıyor. Aynı harita olduğunda if bloğuna giriyor. Fakat if'in içinde de dışında da yapılan çağrı aynı. Dolayısıyla yapılan işlemler de aynı.

Kabaca söylemek gerekirse; eğer loading phase(yükleme ekranı) ekrana gelmişse artık destroy işlemini atlamak neredeyse imkansızdır, çünkü zaten çalışıp işini bitirmiştir bile. Kritik nokta da burası zaten, sağlıklı bir şekilde Destroy'un önüne geçmek.
Fakat buradaki kodlar bunu yapmıyor maalesef, bunu dile getirmek istedim.

Aşağıda hiçbir değişiklik yapmadan sadece syserr yazdıran basit bir test var ve syserr'i de bırakıyorum. Deneyebilirsiniz.
C++:
Genişlet Daralt Kopyala
std::string g_strCachedMapName;
PyObject* netWarp(PyObject* poSelf, PyObject* poArgs)
{
    [...]

    if (!g_strCachedMapName.empty() && g_strCachedMapName == strCurrentMap)
    {
        TraceError("Cache aktif.");
        rkNetStream.Warp(nX, nY);
        return Py_BuildNone();
    }

    rkNetStream.Warp(nX, nY);

    [...]
}

C++:
Genişlet Daralt Kopyala
void CMapManager::Create()
{
    assert(NULL==m_pkMap && "CMapManager::Create");
    if (m_pkMap)
    {
        Clear();
        return;
    }

    m_pkMap = (CMapOutdoor*)AllocMap();
    assert(NULL!=m_pkMap && "CMapManager::Create MAP is NULL");
    TraceError("Harita yeniden olusturuldu.");
}

void CMapManager::Destroy()
{
    stl_wipe_second(m_EnvironmentDataMap);

    if (m_pkMap)
    {
        m_pkMap->Clear();
        delete m_pkMap;
        m_pkMap = NULL;
    }
    TraceError("Harita yok edildi.");
}
Syserr:
Kod:
Genişlet Daralt Kopyala
1002 16:02:10558 :: Harita yok edildi. ( İlk giris )
1002 16:02:10680 :: Harita yeniden olusturuldu. ( İlk giris )
-------------
1002 16:02:29639 :: Harita yok edildi. ( Warp - İkinci ışınlanma)
1002 16:02:30146 :: Cache aktif. ( Warp - İkinci ışınlanma)
1002 16:02:30146 :: Harita yok edildi. ( Warp - İkinci ışınlanma)
1002 16:02:30146 :: Harita yeniden olusturuldu. ( Warp - İkinci ışınlanma)
 
Demek istediğini anlıyorum, zaten kod teoride çalışıyor. Aynı harita olduğunda if bloğuna giriyor. Fakat if'in içinde de dışında da yapılan çağrı aynı. Dolayısıyla yapılan işlemler de aynı.

Kabaca söylemek gerekirse; eğer loading phase(yükleme ekranı) ekrana gelmişse artık destroy işlemini atlamak neredeyse imkansızdır, çünkü zaten çalışıp işini bitirmiştir bile. Kritik nokta da burası zaten, sağlıklı bir şekilde Destroy'un önüne geçmek.
Fakat buradaki kodlar bunu yapmıyor maalesef, bunu dile getirmek istedim.

Aşağıda hiçbir değişiklik yapmadan sadece syserr yazdıran basit bir test var ve syserr'i de bırakıyorum. Deneyebilirsiniz.
C++:
Genişlet Daralt Kopyala
std::string g_strCachedMapName;
PyObject* netWarp(PyObject* poSelf, PyObject* poArgs)
{
    [...]

    if (!g_strCachedMapName.empty() && g_strCachedMapName == strCurrentMap)
    {
        TraceError("Cache aktif.");
        rkNetStream.Warp(nX, nY);
        return Py_BuildNone();
    }

    rkNetStream.Warp(nX, nY);

    [...]
}

C++:
Genişlet Daralt Kopyala
void CMapManager::Create()
{
    assert(NULL==m_pkMap && "CMapManager::Create");
    if (m_pkMap)
    {
        Clear();
        return;
    }

    m_pkMap = (CMapOutdoor*)AllocMap();
    assert(NULL!=m_pkMap && "CMapManager::Create MAP is NULL");
    TraceError("Harita yeniden olusturuldu.");
}

void CMapManager::Destroy()
{
    stl_wipe_second(m_EnvironmentDataMap);

    if (m_pkMap)
    {
        m_pkMap->Clear();
        delete m_pkMap;
        m_pkMap = NULL;
    }
    TraceError("Harita yok edildi.");
}
Syserr:
Kod:
Genişlet Daralt Kopyala
1002 16:02:10558 :: Harita yok edildi. ( İlk giris )
1002 16:02:10680 :: Harita yeniden olusturuldu. ( İlk giris )
-------------
1002 16:02:29639 :: Harita yok edildi. ( Warp - İkinci ışınlanma)
1002 16:02:30146 :: Cache aktif. ( Warp - İkinci ışınlanma)
1002 16:02:30146 :: Harita yok edildi. ( Warp - İkinci ışınlanma)
1002 16:02:30146 :: Harita yeniden olusturuldu. ( Warp - İkinci ışınlanma)
Hm haklı olabilirsiniz, tekrar gözden geçireceğim, dilerseniz, güncelleyene kadar kapatabilirsiniz.
 
Durum
İçerik kilitlendiği için mesaj gönderimine kapatıldı.
Geri
Üst