Re: [Gems-users] Does ruby leak memory?


Date: Wed, 09 Dec 2009 10:15:22 +0100
From: Javi Merino <jmerino@xxxxxxxxxxxxx>
Subject: Re: [Gems-users] Does ruby leak memory?
Dan Gibson wrote:
> Javier,
> As far as Ruby is concerned, It would be safe to reclaim memory used
> by a block when its no longer cache anywhere on-chip(s). In other
> words, if that block was ever accessed again, the DirectoryEntry
> constructor would restore the same state. We've never bothered to
> implement block recycling because the memory usage of Simics has
> always been large anyway (though it can be helped with
> set-memory-limit), and its difficult to tell when blocks really are no
> longer cached (e.g., it is protocol specific).
> 
> Let me, and the list, know how your experiment goes with freeing old
> blocks. I've poked around a bit myself and haven't found any other
> likely culprits (that is not proof that they dont' exist!) -- but
> anecdotally, Ruby is stable to run for weeks at a time in some of my
> longer simulations.

Dan, I modified ruby and the MOESI_CMP_token protocol (see
01_free_unused_directory_entries.patch and
02_MOESI_CMP_token_free_DEs.patch). Both patches are against GEMS 2.1.
After running the same simulation, the memory used by Simics+GEMS was
reduced by 20%. The memory used by the simulator still seems to grow
forever, so I don't know if the issue has really been solved, but at
least this is a nice memory reduction which would help our simulations.

As you pointed out, telling when blocks are no longer cached is protocol
specific. You have to call freeBlocks() at the end of the transition in
the directory (memory) part of slicc. The best place is at the end of
setState(), as you can see in 02_MOESI_CMP_token_free_DEs.

I also attach a patch for MOESI_CMP_NUCA, for those of us who still use
GEMS to simulate NUCAs :-)

Regards,
Javier Merino
Added a DirectoryMemory::freeBlock() method.

The coherence protocol can call this method when a cache block is only present
in memory. This way, the memory used by the simulation doesn't keep growing
and growing.

diff --git a/ruby/system/DirectoryMemory.C b/ruby/system/DirectoryMemory.C
--- a/ruby/system/DirectoryMemory.C
+++ b/ruby/system/DirectoryMemory.C
@@ -172,8 +172,7 @@ Directory_Entry& DirectoryMemory::lookup
   return (*entry);
 }
 
-/*
-void DirectoryMemory::invalidateBlock(PhysAddress address)
+void DirectoryMemory::freeBlock(const PhysAddress& address)
 {
   assert(isPresent(address));
 
@@ -183,13 +182,10 @@ void DirectoryMemory::invalidateBlock(Ph
     ERROR_MSG("Directory Memory Assertion: accessing memory out of range.");
   }
 
-  if(m_entries[index] != NULL){
-    delete m_entries[index];
-    m_entries[index] = NULL;
-  }
-
+  ASSERT(m_entries[index]);
+  delete m_entries[index];
+  m_entries[index] = NULL;
 }
-*/
 
 void DirectoryMemory::print(ostream& out) const
 {
diff --git a/ruby/system/DirectoryMemory.h b/ruby/system/DirectoryMemory.h
--- a/ruby/system/DirectoryMemory.h
+++ b/ruby/system/DirectoryMemory.h
@@ -84,6 +84,7 @@ public:
   static void printConfig(ostream& out);
   bool isPresent(PhysAddress address);
   Directory_Entry& lookup(PhysAddress address);
+  void freeBlock(const PhysAddress&);
 
   void print(ostream& out) const;
 
Added calls to DirectoryMemory::freeBlock() in MOESI_CMP_token.

diff --git a/protocols/MOESI_CMP_token-dir.sm b/protocols/MOESI_CMP_token-dir.sm
--- a/protocols/MOESI_CMP_token-dir.sm
+++ b/protocols/MOESI_CMP_token-dir.sm
@@ -104,6 +104,7 @@ machine(Directory, "Token protocol") {
 
   external_type(DirectoryMemory) {
     Entry lookup(Address);
+    void freeBlock(Address);
     bool isPresent(Address);
   }
 
@@ -136,6 +137,12 @@ machine(Directory, "Token protocol") {
       assert(directory[addr].Tokens >= 1); // Must have at least one token
       // assert(directory[addr].Tokens >= (max_tokens() / 2)); // Only mostly true; this might not always hold
     }
+
+    // If memory has all the tokens, there's no copy of the block in the
+    // chip so we can claim back some memory.
+    if (directory[addr].Tokens == max_tokens()) {
+      directory.freeBlock(addr);
+    }
   }
   
   // ** OUT_PORTS **

Attachment: mbytes_used.png
Description: PNG image

Added calls to DirectoryMemory::freeBlock() in MOESI_CMP_NUCA

diff --git a/protocols/MOESI_CMP_NUCA-dir.sm b/protocols/MOESI_CMP_NUCA-dir.sm
--- a/protocols/MOESI_CMP_NUCA-dir.sm
+++ b/protocols/MOESI_CMP_NUCA-dir.sm
@@ -62,6 +62,7 @@ machine(Directory, "DNUCA protocol") {
 
   external_type(DirectoryMemory) {
     Entry lookup(Address);
+    void freeBlock(Address);
     bool isPresent(Address);
   }
 
@@ -109,6 +110,10 @@ machine(Directory, "DNUCA protocol") {
       assert(directory[addr].Tokens == max_tokens()); // all tokens
       assert(directory[addr].Dirty == false);
     }
+
+    if (directory[addr].Tokens == max_tokens()) {
+      directory.freeBlock(addr);
+    }
   }
 
   // Add function here

Attachment: signature.asc
Description: Esta parte del mensaje =?ISO-8859-1?Q?est=E1?= firmada digitalmente

[← Prev in Thread] Current Thread [Next in Thread→]