Python'da Sahte Bellek Sızıntısı: ru_maxrss ve VmRSS Karışıklığı
Bir RAG pipeline'ında RSS değerinin hep arttığını gören yazar, aslında ru_maxrss'in tepe değer olduğunu keşfetti. Doğru ölçüm için VmRSS kullanımı ve batch encoding çözümü.
Bir geliştirici, web makalelerini parçalayıp embedding'e çevirerek Qdrant'a aktaran bir RAG pipeline'ı geliştirirken RSS bellek kullanımının sürekli arttığını ve 1GB limitini aştığını fark etti. gc.collect() ve del çağrıları eklemesine rağmen sayı hiç düşmedi; bu da bellek sızıntısı olduğu izlenimi yarattı. Sorunun kaynağı ise Python'ın resource.getrusage() fonksiyonundaki ru_maxrss alanıydı: bu değer, sürecin başlangıcından bu yana ulaşılan en yüksek bellek kullanımını (peak) gösterir, anlık kullanımı değil. Bir kez tepe noktaya ulaşıldığında bu sayı asla düşmez, bu yüzden her sonraki limit kontrolü başarısız olur.
Çözüm, Linux'ta /proc/self/status dosyasından anlık VmRSS değerini okumaktı. Bu değişiklikten sonra loglar gerçekçi biçimde inip çıkmaya başladı ve gerçek bellek kullanımının, model yüklendikten sonra yaklaşık 1.8GB'de stabil kaldığı ortaya çıktı — hiçbir sızıntı yoktu. Ayrıca 1GB'lık limitin baştan gerçekçi olmadığı, çünkü kullanılan multilingual-e5-base modelinin kendisinin yüklenir yüklenmez yaklaşık 1.6GB bellek tükettiği anlaşıldı.
Yazar ayrıca embedding üretimini tek tek chunk yerine 50'li batch'ler halinde yaparak performansı artırdı, torch.no_grad() kullanarak gereksiz gradyan tamponlarından kaçındı ve e5 ailesi modellerin gerektirdiği 'passage:' / 'query:' önek kurallarına dikkat çekti. Pipeline, kesintiye dayanıklı hale getirilerek qdrant_id alanı boş olan kayıtlardan devam edecek şekilde tasarlandı. Temel ders: bir metrik anlık mı yoksa tepe değer mi ölçüyor, bunu doğrulamadan bellek sızıntısından şüphelenmemek gerekiyor.