Patchwork ui: remove urllib2 from being imported early

login
register
mail settings
Submitter via Mercurial-devel
Date Feb. 14, 2017, 6:15 p.m.
Message ID <1f3234760225170767d1.1487096110@dragonair.mtv.corp.google.com>
Download mbox | patch
Permalink /patch/18481/
State Accepted
Headers show

Comments

via Mercurial-devel - Feb. 14, 2017, 6:15 p.m.
# HG changeset patch
# User Kyle Lippincott <spectral@google.com>
# Date 1486897598 28800
#      Sun Feb 12 03:06:38 2017 -0800
# Node ID 1f3234760225170767d10bfcd9cc5b2431b65471
# Parent  72f25e17af9d6a206ea374c30f229ae9513f3f23
ui: remove urllib2 from being imported early

Before this change, urllib2 was brought in when constructing the ui object, and
that added ~5ms on my Linux workstation to the hg startup time for every
command, bringing the time for 'HGRCPATH=/dev/null hg root' from 46ms to 40ms.

Now, we construct a single proxy object per initial ui creation (so that if the
ui is copied they share the object), but defer the actual instantiation of it
and the import of urllib2 until it's needed.
Augie Fackler - Feb. 14, 2017, 6:31 p.m.
On Tue, Feb 14, 2017 at 10:15:10AM -0800, Kyle Lippincott via Mercurial-devel wrote:
> # HG changeset patch
> # User Kyle Lippincott <spectral@google.com>
> # Date 1486897598 28800
> #      Sun Feb 12 03:06:38 2017 -0800
> # Node ID 1f3234760225170767d10bfcd9cc5b2431b65471
> # Parent  72f25e17af9d6a206ea374c30f229ae9513f3f23
> ui: remove urllib2 from being imported early

Queued, thanks for fighting the good fight on startup time.

>
> Before this change, urllib2 was brought in when constructing the ui object, and
> that added ~5ms on my Linux workstation to the hg startup time for every
> command, bringing the time for 'HGRCPATH=/dev/null hg root' from 46ms to 40ms.
>
> Now, we construct a single proxy object per initial ui creation (so that if the
> ui is copied they share the object), but defer the actual instantiation of it
> and the import of urllib2 until it's needed.
>
> diff -r 72f25e17af9d -r 1f3234760225 mercurial/ui.py
> --- a/mercurial/ui.py	Mon Feb 13 02:31:56 2017 -0800
> +++ b/mercurial/ui.py	Sun Feb 12 03:06:38 2017 -0800
> @@ -94,6 +94,24 @@
>  # pager =""",
>  }
>
> +
> +class httppasswordmgrdbproxy(object):
> +    """Delays loading urllib2 until it's needed."""
> +    def __init__(self):
> +        self._mgr = None
> +
> +    def _get_mgr(self):
> +        if self._mgr is None:
> +            self._mgr = urlreq.httppasswordmgrwithdefaultrealm()
> +        return self._mgr
> +
> +    def add_password(self, *args, **kwargs):
> +        return self._get_mgr().add_password(*args, **kwargs)
> +
> +    def find_user_password(self, *args, **kwargs):
> +        return self._get_mgr().find_user_password(*args, **kwargs)
> +
> +
>  class ui(object):
>      def __init__(self, src=None):
>          """Create a fresh new ui object if no src given
> @@ -145,7 +163,7 @@
>              # shared read-only environment
>              self.environ = encoding.environ
>
> -            self.httppasswordmgrdb = urlreq.httppasswordmgrwithdefaultrealm()
> +            self.httppasswordmgrdb = httppasswordmgrdbproxy()
>
>          allowed = self.configlist('experimental', 'exportableenviron')
>          if '*' in allowed:
> @@ -172,7 +190,7 @@
>          """Clear internal state that shouldn't persist across commands"""
>          if self._progbar:
>              self._progbar.resetstate()  # reset last-print time of progress bar
> -        self.httppasswordmgrdb = urlreq.httppasswordmgrwithdefaultrealm()
> +        self.httppasswordmgrdb = httppasswordmgrdbproxy()
>
>      def formatter(self, topic, opts):
>          return formatter.formatter(self, topic, opts)
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Patch

diff -r 72f25e17af9d -r 1f3234760225 mercurial/ui.py
--- a/mercurial/ui.py	Mon Feb 13 02:31:56 2017 -0800
+++ b/mercurial/ui.py	Sun Feb 12 03:06:38 2017 -0800
@@ -94,6 +94,24 @@ 
 # pager =""",
 }
 
+
+class httppasswordmgrdbproxy(object):
+    """Delays loading urllib2 until it's needed."""
+    def __init__(self):
+        self._mgr = None
+
+    def _get_mgr(self):
+        if self._mgr is None:
+            self._mgr = urlreq.httppasswordmgrwithdefaultrealm()
+        return self._mgr
+
+    def add_password(self, *args, **kwargs):
+        return self._get_mgr().add_password(*args, **kwargs)
+
+    def find_user_password(self, *args, **kwargs):
+        return self._get_mgr().find_user_password(*args, **kwargs)
+
+
 class ui(object):
     def __init__(self, src=None):
         """Create a fresh new ui object if no src given
@@ -145,7 +163,7 @@ 
             # shared read-only environment
             self.environ = encoding.environ
 
-            self.httppasswordmgrdb = urlreq.httppasswordmgrwithdefaultrealm()
+            self.httppasswordmgrdb = httppasswordmgrdbproxy()
 
         allowed = self.configlist('experimental', 'exportableenviron')
         if '*' in allowed:
@@ -172,7 +190,7 @@ 
         """Clear internal state that shouldn't persist across commands"""
         if self._progbar:
             self._progbar.resetstate()  # reset last-print time of progress bar
-        self.httppasswordmgrdb = urlreq.httppasswordmgrwithdefaultrealm()
+        self.httppasswordmgrdb = httppasswordmgrdbproxy()
 
     def formatter(self, topic, opts):
         return formatter.formatter(self, topic, opts)