Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Yazı Tipi BoyutlandırıcıAa
  • Anasayfa
  • Teknoloji
    • Siber Güvenlik
    • Yapay Zeka
    • Donanım
    • Bilim
  • Yazılım
  • Savunma & İstihbarat
  • Oyun
  • Yaşam
    • Finans
    • Sinema
    • Dünyadan Haberler
  • İş Birliği
Okuma: Hafıza mükemmel, ancak uygulama yavaş kalıyordu.
Paylaş
Yazı Tipi BoyutlandırıcıAa
Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Ara
Bizi Takip Et
  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti
© 2026 Teknomers. All Rights Reserved.

Anasayfa » Hafıza mükemmel, ancak uygulama yavaş kalıyordu.

Yazılım

Hafıza mükemmel, ancak uygulama yavaş kalıyordu.

teknomers
Son güncelleme: 25 Temmuz 2026 22:39
teknomers
Paylaş
Paylaş

Giriş

SaaS uygulamamda sayfa geçişleri gecikmeli gerçekleşiyordu. Kullanıcı on saniye beklememekteydi, ama uygulamanın ucuz görünmesini sağlayan kısa ve sürekli bir yavaşlık söz konusu. Problemi çözmeye oturdum ve zihnimde hazır bir hipotez ile: bir yerde caching yoktu.

Yanılmışım ve yanlış hipotezim sorunu bulmamı engellemişti. Darboğaz, önceden düşündüğüm hiçbir şeyde değildi; çünkü bu katman çok iyi çalışıyordu ve dikkatimizi çekmiyordu.

<h2>Mevcut Durum ve Yetersizlikleri</h2>
<p>Projemdeki cache kurulumları vasat değil, düzgün bir şekilde yapılandırılmıştı. <code>TenantCache</code> ve <code>GlobalCache</code> adında iki ince katman, Laravel'in cache yapısını sararak, üç ana unsur sağlıyordu: her anahtar takım kapsamı ile başlıyor (<code>t{teamId}:{domain}:{suffix}</code>), her giriş bir enum ile belirlenen TTL ile başlıyor ve her giriş blok invalidation için bir tag ile başlıyor. <code>flexible</code> ile sıcak yerlerde stale-while-revalidate uygulandı, veri değiştiğinde observer invalidation çalışıyor ve <code>Cache::</code> ile <code>cache()</code> gibi doğrudan çağrılar, mimari testlerindeki kısıtlamalar nedeniyle yasaklandı.</p>
<p>İnformasyona sahip olduğum bu altyapının en çok gurur duyduğum kısmıydı; ancak bu problemle hiçbir ilgisi yoktu.</p>
<p>Dersim, yanlış yerlerde arayarak zaman kaybettikten sonra anladığım bir şeydi: <strong>cache, tekrarlanan pahalı hesaplamaları çözümler. Kullanıcı her mobil geçişte baştan aşağı yeniden hesaplanıyorsa, cache bir çözüm değildir.</strong> Eğer maliyet "her zaman çalışan yirmi basit query" ise, cache seni kurtaramaz; çünkü depolayacak pahalı bir yanıt yoktur. Sadece çok fazla küçük şey sürekli olarak oluşuyordur.</p>

<h2>Gerçek Problem Yeri</h2>
<p>Inertia'da her sayfa geçişi, sunucuya tam bir request göndermektedir. Ve merkezi bir yer olan <code>HandleInertiaRequests</code>, her sayfanın aldığı paylaşılan prop'ları inşa etmektedir: oturum açmış kullanıcı, kullanıcı ekipleri, mevcut ekip, izinler, plan özellikleri, navigasyon sayacı. Bu, <strong>her navigasyonda yeniden oluşturulmakta</strong>. Sistem genelinde en fazla çalıştırılan kod ve performansı incelediğinizde en az dikkat çekeni, çünkü kimse shared props'ın middleware'ini, yavaş bir sorgu olup olmadığını kontrol etmek için açmaz.</p>

<p>Query kayıtlarını açtım ve saydım. On takım ile bir kullanıcı, her geçişte 27 sorgu yapıyordu. İki sebep vardı ve her ikisi de klasik bir durumu yansıtıyordu.</p>

<p>İlki, bir rahatlık metodunun arkasında gizlenmiş bir N+1 sorunudur. <code>toUserTeams()</code> tüm takımları tek bir sorguda alıyor, güzel görünüyor ve ardından her takım için bir payload oluşturmak için haritalama işlemi gerçekleştiriyor. Ama bu haritalama içinde <code>teamRole($team)</code> fonksiyonu, kullanıcının o takımda hangi rolde olduğunu öğrenmek üzere bir sorgu çalıştırıyordu. Her takım için ayrı bir sorgu. Eager loading doğru yerde olsa da, takımları yükleyip her seferinde üyelikleri birer birer sorguluyordum. Kullanıcı her yeni takımla her tıkında yeni bir sorgu ekleniyordu.</p>

<p>İkinci durum ise beni en çok sinirlendiren bir konu. Inertia'nın özel bir tuzağı. Props'lar closure olarak yazılmış ve bağımsız olarak değerlendiriliyor:</p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="c1">// app/Http/Middleware/HandleInertiaRequests.php</span>

‘currentTeam’ => fn () => $this->resolveCurrentUserTeam($user),
‘teamPermissions’ => fn () => $user->toTeamPermissions($this->resolveActiveTeam($user)),
‘teamFeatures’ => fn () => $this->teamFeatures($this->resolveActiveTeam($user)),
‘teamTrial’ => fn () => $this->teamTrial($this->resolveActiveTeam($user)),

<p>Dört farklı prop, aktif takıma ihtiyacını duyuyor ve <code>resolveActiveTeam</code> bunları dört kez sıfırdan çözüyor: oturumu okuyor, takımı sorguluyor, kullanıcının o takıma üye olup olmadığını kontrol ediyor. Dört kez aynı iş, her istek için. Her satır için sorun yok, bu nedenle kod incelemelerinde gözden kaçıyor; çünkü bunların hiçbirinde bir yanlışlık yok, ancak toplamda dört tane olduğu için...</p>

<p>Çözüm birkaç satıra sığdırılabilir. İlişkiyi bir kez yükleyip, payload oluşturulurken kullanmalıyız:</p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="c1">// app/Http/Middleware/HandleInertiaRequests.php</span>

// Bir membership okuması ile tüm payload: takımlar, currentTeam ve
// teamPermissions hepsi rolü çözüyor ve toUserTeams() her takım için bir kere bunu yapıyor.
$user?->load(‘teamMemberships’);

Contents
  • Giriş
  • Üç Önemli Kural
  • Sonuç Olarak
<p>Ve <code>teamRole()</code>, eğer ilişkiler zaten bellekte varsa, bunu tercih ederek geçiyor:</p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="c1">// app/Concerns/HasTeams.php</span>

public function teamRole(Team $team): ?TeamRole
{
if ($this->relationLoaded(<span class=”s1>’teamMemberships’)) {
return $this->teamMemberships->firstWhere(<span class=”s1>’team_id’, $team->id)?->role;
}

<span class="k">return</span> <span class="nv">$this</span><span class="o">-&gt;</span><span class="nf">teamMemberships</span><span.p>(</span><span class="s1>'team_id'</span><span class="p">,</span> <span class="nv">$team</span><span.class="o">-&gt;</span><span class="n">id</span><span.class="p">)</span><span.class="o">-&gt;</span><span.class="nf">first</span><span.class="p">()</span><span.class="o">?-&gt;</span><span.class="n">role</span><span.class="p">;</span>

}

<p>Aktif takımın daha fazla bellekle tutulması, 15 query yapılmasını sağladı ve bu sayı oldukça iyi. Ama önemli olan nokta, şimdi bu maliyetin sabit olması. Önceden, her geçişte kullanıcıların takım sayısına göre maliyet büyüyordu, bu da uygulamayı en çok etkileyecek duruma sokuyordu. Bu tür bir büyüme, üretimde keşfetmek istemeyeceğiniz bir durum.</p>

<h2>İlk Durum Hatalıydı</h2>
<p>Şimdi asıl ilgi çekici kısma gelelim: <code>teamRole()</code> daha hızlı hale geldiğinde <code>belongsToTeam()</code> de öyle olmalıydı, değil mi? Aynı tabloya, aynı soruya yanıt verecek ve her istekte birkaç kez çağrılacak. Bariz değişikliği yaptım. <strong>208 test bozuldu.</strong></p>

<p>Testlerin birdenbire bozulması ilk anda testlerin yanlış olduğuna inanma ya da test kurulumlarının hatalı olduğunu düşünme isteği doğuruyor. Ama sorun değil, gerçek bir bug ortaya çıkıyordu: kullanıcının bir takıma daveti kabul etmesi gerçekleşiyordu. Bu işlem esnasında üyelik veritabanında oluşturuluyordu. Ardından, aynı istekte <code>switchTeam()</code>, o takıma geçip geçemeyeceğini kontrol etmek için <code>belongsToTeam()</code> çağrısı yapıyordu. Bellekte bir ilişki yüklüyken, bu okuma yazmadan sonraki durumu görmemekteydi. Üyelik veritabanındaysa mevcut, ancak bellekdeki nesne bunu bilmediği için <code>belongsToTeam()</code> "aparten olur" diyordu ve <code>switchTeam()</code> başaramıyordu..</p>

<p>Açık bir hata yoktu. Hata kaydı yoktu. Tekrar yüklendiğinde ekibi yanlış yerde görünüyordu.</p>

<p>Aynı düşman, yine iki önceki gönderide olduğu gibi. Orada bir yeşil teste yanlış kapı açarken, burada da gerçek bir hız optimizasyonu sağlamaya çalışırken, doğrudan doğruya düzgün bir şekilde verdim. <strong>Otomasyon, bir şeyin bozulduğunda uyarı vermez; hızlı ve yanlış hale getirir ki bu, yavaş ama doğru olmaktan çok daha tehlikeli.</strong></p>

<p>Bu nedenle <code>belongsToTeam()</code> kesin bir şekilde sorgulama yapmak durumunda kalarak, kodda bir yorum yapılması gerekti. Çünkü bir karara dayanarak yapılan bir tasarım, sonraki kişi (ya da sonraki yapay zeka) bunu optimize ettiğini düşündü:</p>

<div class="highlight js-code-highlight">
    <pre class="highlight php"><code><span class="c1">// app/Concerns/HasTeams.php</span>

/ 

  • Hiçbir zaman önbelleğe alma, başka birinin her zaman veritabanını sorgulayan bir işlev.

  • switchTeam() hemen bir davet geldiğinde bu ilişkide ki durum bilgisini aldıktan sonra kontrol eder ve

  • önbellekteki bilgi, yazma işleminden önceki hali göstermekte olur: değişim sessiz bir şekilde başarısız olur ve kullanıcı eski takımla kalır.
    */

    Üç Önemli Kural

    1. Cache’den önce sayın. Cache, herkesin ilk hipotezidir ve tekrarlanan pahalı hesaplamaları çözer. Eğer maliyet küçük ve çok sayıda sorgu ise, cache ihtiyacınız olan bir çözüm değil, sorgularınızı azaltmanın bir yoludur.
    2. İlk önce tüm geçişlerde çalışan koda bakın. Inertia’da bu shared props’dır, kendi yapınızda başka bir isimle anılabilir. Bu, sistem genelinde en çok çalışan koddur ve en az gözden geçirilen kısımdır; çünkü bu bir özellik ile ilgili değildir. Gereksiz bir sorgu orada, açılmayan bir sayfadakine göre daha fazla maliyetlidir.
    3. Önbellekteki ilişki sadece görüntülemek için, asla karar vermek için değildir. Bellekten çekim yaparken ekranı oluşturmavnızı sağlamak sorun değil. Ancak bir yetkilendirme, giriş ya da durum değişikliğinde, veritabanındaki güncel bilgilere karar vermeniz gerekir.

    Sonuç Olarak

    Buradaki asıl kazanım 27 sorgudan 15’e geçmek değil, bir eğrinin sabit bir hale getirilmesidir. Bunu ancak kolay hipotez (cache) işe yaramadığında ve ölçüm yapmaya zorlandığımda buldum.

    Yine görülmesi gereken bir durum vardı: her takım ile birlikte hâlâ her istekte dört kez üyelik kontrolü yapılıyor. Derinlemesine incelemeyle bu durum, diğer sorgu sayısını arttıracak veya azaltacaktır. Test, dört tane değişken ile sınırlı kalacak, bu sayı asla artamayacaktır. Eğer bir gün beş olursa, bu durum tekrardan birkaç deneme ile ortaya çıkacak ve bunu bilmek istiyorum.

    Eğer uygulamanız “neden yavaş olduğunu anlayamadığınız” noktada takılı kalıyorsa, bu sorunun bulunduğunuz sayfada olmadığını varsayıyorum. Shared props middleware’in kayıtlarını açın ve sorguları sayın. Ne bulduğunuzu bana bildirin.

Kaynak: Orijinal Makale

İlk Kez Sunucu Yöneticisi Olanların Yaptığı 7 Hata (ve Deploynix’in Bunları Nasıl Önlediği)
Parolaları Saklamayı Durdur: Laravel ile Kurumsal SSO Oluşturun 🛡️
Inertia.js Uygulamanızı Sessizce Bozar
Haven – Gayrimenkul Yönetim Sistemi
WinRavel: Tüm Laravel Uygulamasını Tek Bir Windows .exe Dosyasına Paketledim (FrankenPHP + MariaDB Dahil)
Bu Makaleyi Paylaş
Facebook Bağlantıyı Kopyala Yazdır
Paylaş
Önceki Makale Elon Musk’ın Boring Şirketi Dev Bir Yatırım Sürecine Girdi
Sonraki Makale Microsoft, PC için Xbox 360 emülatörü sundu; modüler çözümlerle oyunlar çalıştı.

Sanal Medya

FacebookBeğen
452Takip Et
PinterestSabitle
237Takip Et

Son Eklenenler

Spyware Üreticilerine Darbe Vuran Hacker Kimdir?
Genel
Amazon, Warner Bros’un İddiasına Göre Yönetici Çalışanları Hedefliyor
Genel
Ukrayna yanlısı grup, Rus drone savunmasını hacklediğini iddia etti
Donanım
Acil: Malvertising, Kötü Amaçlı Yazılımı Parça Parça Yaygınlaştırıyor
Siber Güvenlik
Rusya’nın en büyük bankası Sberbank, Aralık’a kadar kripto ticareti altyapısı kurmayı planlıyor
Finans
Microsoft, PC için Xbox 360 emülatörü sundu; modüler çözümlerle oyunlar çalıştı.
Donanım
//

Siber güvenlik, yapay zeka ve savunma sanayiinden; finans ve sinema dünyasına uzanan geniş bir yelpaze. Teknomers; teknoloji, strateji ve yazılım dünyasını sade bir dille sizlerle buluşturuyor.

Kurumsal

  • Hakkımızda
  • Gizlilik politikası
  • Tanıtım Yazısı ve Backlink Hizmeti

Kategoriler

  • Teknoloji
  • Oyun
  • Sinema
  • Siber Güvenlik
  • Bilim
  • Finans
  • Dünyadan Güncel Haberler

Populer

  • TV'de Ücretsiz İzlenebilen Şifresiz Erotik Kanallar (2025 Güncel Frekans Listesi)

  • The Last of Us PC Kontrolleri: Hızlı Silah Değiştirme ve Tüm Tuşlar (2025)

  • Hogwarts Legacy'de Odaklanma İksiri Nasıl Yapılır?

Teknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor HaberleriTeknomers | Dünyadan Güncel Teknoloji | Oyun | Müzik | Film | Spor Haberleri
Bizi Takip Et
© 2026 Teknomers. All Rights Reserved.
Welcome Back!

Sign in to your account

Kullanıcı Adı veya E-posta Adresi
Şifre

Şifrenizi mi unuttunuz?