Patchwork [1,of,6,V2] util: add a 'nogc' decorator to disable the garbage collection

login
register
mail settings
Submitter Pierre-Yves David
Date Dec. 4, 2014, 3:16 p.m.
Message ID <52fbb116345b349dbd2b.1417706174@marginatus.alto.octopoid.net>
Download mbox | patch
Permalink /patch/6999/
State Accepted
Headers show

Comments

Pierre-Yves David - Dec. 4, 2014, 3:16 p.m.
# HG changeset patch
# User Pierre-Yves David <pierre-yves.david@fb.com>
# Date 1417700620 28800
#      Thu Dec 04 05:43:40 2014 -0800
# Node ID 52fbb116345b349dbd2bd3fbbe49bc7e09227365
# Parent  c237499a7fba65c88a2da721a22b66df4f39cf4e
util: add a 'nogc' decorator to disable the garbage collection

Garbage collection behave pathologically when creating a lot of containers. As
we do that more than once it become sensible to have a decorator for it. See
inline documentation for details.

Patch

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -18,10 +18,11 @@  import i18n
 import error, osutil, encoding
 import errno, shutil, sys, tempfile, traceback
 import re as remod
 import os, time, datetime, calendar, textwrap, signal, collections
 import imp, socket, urllib
+import gc
 
 if os.name == 'nt':
     import windows as platform
 else:
     import posix as platform
@@ -542,10 +543,32 @@  def always(fn):
     return True
 
 def never(fn):
     return False
 
+def nogc(func):
+    """disable garbage collector
+
+    Python's garbage collector triggers a GC each time a certain number of
+    container objects (the number being defined by gc.get_threshold()) are
+    allocated even when marked not to be tracked by the collector. Tracking has
+    no effect on when GCs are triggered, only on what objects the GC looks
+    into. As a workaround, disable GC while building complexe (huge)
+    containers.
+
+    This garbage collector issue have been fixed in 2.7.
+    """
+    def wrapper(*args, **kwargs):
+        gcenabled = gc.isenabled()
+        gc.disable()
+        try:
+            return func(*args, **kwargs)
+        finally:
+            if gcenabled:
+                gc.enable()
+    return wrapper
+
 def pathto(root, n1, n2):
     '''return the relative path from one place to another.
     root should use os.sep to separate directories
     n1 should use os.sep to separate directories
     n2 should use "/" to separate directories