title: firefox high memory (RAM) usage, how to free with javascript?
body: <p>I notice that after using firefox for a couple of hours it gets more that 2gb of ram memory. It happens expecially when I upload big files (100mb-400mb) with ajax uploader, and also happens when I open to many images (for example 16mb of total images on a web page).</p>
  
  <p>The problem is that even after upload finish or after closing the images pages the memory is not getting free, firefox still have 2gb of ram memory.
  Is there a way from javascript to make firefox free the memory, for example when upload finish or after images are loaded or closed?</p>
  
  <p><strong>EDIT</strong>
  From <code>about:memory</code> :
  1,172.03 MB (100.0%) -- explicit</p>
  
  <p>├──1,000.00 MB (85.32%) -- js</p>
  
  <p>│  ├────863.97 MB (73.72%) -- compartment([System Principal], 0x5083000)</p>
  
  <p>│  │    ├──819.31 MB (69.91%) ── string-chars</p>
  
  <p>How can I empty <strong>string-chars</strong> that I am pretty sure this comes when the files are readed into memory and then uploaded with ajax?</p>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>Here is the recrusive function causing this memory usage:</p>
  
  <pre><code>function uploadAjax(file, startByte, index)
  {
      if(startByte==0)
      {
          $('#progress'+index).html(' ').progressbar( "destroy" ).progressbar();
          $('#asyncuploadsingle'+index).attr('disabled', true);
      }
  
      var size        = file.size;
      var chunkSize   = 2097152;//2 megabyte
      var endByte     = chunkSize + startByte;
      var isLast      = (size - endByte &lt;= 0);
      var chunk       = file;
      var xhr         = new XMLHttpRequest();//prepare xhr for upload
      var chunkNum    = endByte / chunkSize;
  
      if(chunkSize == 0)//no divide
      {
          chunk   = file;
          isLast  = true;
      }
      else if(file.mozSlice) // moz slice
      {
          chunk   = file.mozSlice(startByte, endByte);
      }
      else if(file.webkitSlice) //webkit slice
      {
          chunk   = file.webkitSlice(startByte, endByte);
      }
      else if(file.slice) // w3c slice
      {
          chunk   = file.slice(startByte, chunkSize);
      }
      else
      {
          chunk   = file;
          isLast  = true;
      }
  
      //progress function, with ajax upload progress can be monitored
      xhr.upload.addEventListener('progress', function(e)
      {
          if (e.lengthComputable) 
          {
              var perc = Math.round((e.loaded + chunkNum * chunkSize - chunkSize) * 100 / size);
              //console.log(perc+':'+index);
              $('#progress'+index).progressbar("option", "value", perc);
          }  
      }, false); 
  
      xhr.upload.onabort=function(e)  {   
          finishUp(index,'Aborted');
      };  
  
      xhr.upload.addEventListener('error', function(e){
          finishUp(index, this.responseText+'---&gt;'+name);
      }, false);  
  
      xhr.onreadystatechange=function()
      {
          if(this.readyState == 4 &amp;&amp; this.status == 200)
          {
              try
              {
                  var ret = JSON.parse(this.responseText);
  
                  if(isLast)
                  {
                      finishUp(index,'');
                  }
                  else if(ret.status == 'error')
                  {
                      throw ret.info;
                  }
                  else
                  {
                      uploadAjax(file, endByte, index);
                  }
              }
              catch(err)
              {
                  finishUp(index, err);
              }
  
              delete chunk;
          }
      };
  
      var path    = get_final_path();
      var url     = "filetransfer/uploadfiles.php?ax-file-name="+encodeURIComponent(file.name)+"&amp;ax-file-path="+encodeURIComponent(path)+'&amp;ax-start-byte='+startByte;
  
      xhr.open("POST", url, true);
      xhr.setRequestHeader('Cache-Control', 'no-cache');
      xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');//header
      xhr.setRequestHeader('Content-Type', 'application/octet-stream');//generic stream header
  
      /*var reader = new FileReader();
      reader.onload = function(evt) {  
          xhr.sendAsBinary(evt.target.result);  
      };  
      reader.readAsBinaryString(chunk);
      */  
      xhr.send(chunk);
  
      return xhr;
  }
  </code></pre>
  
  <p>Any point where to optimize it or where to free objects?</p>