##// END OF EJS Templates
bdiff: don't check border condition in loop...
bdiff: don't check border condition in loop `plast = a + len - 1`. So, this "for" loop iterates from "a" to "plast", inclusive. So, `p == plast` can only be true on the final iteration of the loop. So checking for it on every loop iteration is wasteful. This patch simply decreases the upper bound of the loop by 1 and adds an explicit check after iteration for the `p == plast` case. We can't simply add 1 to the initial value for "i" because that doesn't do the correct thing on empty input strings. `perfbdiff -m 3041e4d59df2` on the Firefox repo becomes significantly faster: ! wall 0.072763 comb 0.070000 user 0.070000 sys 0.000000 (best of 100) ! wall 0.053221 comb 0.060000 user 0.060000 sys 0.000000 (best of 100) For the curious, this code has its origins in 8b067bde6679, which is the changeset that introduced bdiff.c in 2005. Also, GNU diffutils is able to perform a similar line-based diff in under 20ms. So there's likely more perf wins to be found in this code. One of them is the hashing algorithm. But it looks like mpm spent some time testing hash collisions in d0c48891dd4a. I'd like to do the same before switching away from lyhash, just to be on the safe side.

File last commit:

r30303:ad40d307 default
r30308:d500ddae default
Show More
pycompat.py
210 lines | 5.5 KiB | text/x-python | PythonLexer
timeless
pycompat: add empty and queue to handle py3 divergence...
r28818 # pycompat.py - portability shim for python 3
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
"""Mercurial portability shim for python 3.
This contains aliases to hide python version-specific details from the core.
"""
from __future__ import absolute_import
Pulkit Goyal
py3: add a bytes version of os.name...
r30302 import os
Pulkit Goyal
pycompat: make pycompat demandimport friendly...
r29584 import sys
Yuya Nishihara
pycompat: provide 'ispy3' constant...
r30030 ispy3 = (sys.version_info[0] >= 3)
if not ispy3:
Pulkit Goyal
py3: conditionalize cPickle import by adding in util...
r29324 import cPickle as pickle
Pulkit Goyal
pycompat: make pycompat demandimport friendly...
r29584 import cStringIO as io
Pulkit Goyal
py3: conditionalize httplib import...
r29455 import httplib
Pulkit Goyal
pycompat: make pycompat demandimport friendly...
r29584 import Queue as _queue
Pulkit Goyal
py3: conditionalize SocketServer import...
r29433 import SocketServer as socketserver
Pulkit Goyal
pycompat: make pycompat demandimport friendly...
r29584 import urlparse
Pulkit Goyal
py3: conditionalize xmlrpclib import...
r29432 import xmlrpclib
Pulkit Goyal
pycompat: make pycompat demandimport friendly...
r29584 else:
import http.client as httplib
import io
import pickle
import queue as _queue
import socketserver
import urllib.parse as urlparse
Pulkit Goyal
py3: conditionalize xmlrpclib import...
r29432 import xmlrpc.client as xmlrpclib
Pulkit Goyal
py3: conditionalize the urlparse import...
r29431
Yuya Nishihara
pycompat: provide 'ispy3' constant...
r30030 if ispy3:
Yuya Nishihara
py3: move xrange alias next to import lines...
r29797 import builtins
Yuya Nishihara
py3: provide (del|get|has|set)attr wrappers that accepts bytes...
r29799 import functools
Martijn Pieters
py3: add an os.fsencode backport to ease path handling
r30119 fsencode = os.fsencode
Pulkit Goyal
py3: add os.fsdecode() as pycompat.fsdecode()...
r30300 fsdecode = os.fsdecode
Pulkit Goyal
py3: add a bytes version of os.name...
r30302 # A bytes version of os.name.
osname = os.name.encode('ascii')
Pulkit Goyal
py3: have pycompat.ospathsep and pycompat.ossep...
r30303 ospathsep = os.pathsep.encode('ascii')
ossep = os.sep.encode('ascii')
Yuya Nishihara
py3: move xrange alias next to import lines...
r29797
Yuya Nishihara
pycompat: extract function that converts attribute or encoding name to str...
r30032 def sysstr(s):
"""Return a keyword str to be passed to Python functions such as
getattr() and str.encode()
This never raises UnicodeDecodeError. Non-ascii characters are
considered invalid and mapped to arbitrary but unique code points
such that 'sysstr(a) != sysstr(b)' for all 'a != b'.
"""
if isinstance(s, builtins.str):
return s
return s.decode(u'latin-1')
Yuya Nishihara
py3: provide (del|get|has|set)attr wrappers that accepts bytes...
r29799 def _wrapattrfunc(f):
@functools.wraps(f)
def w(object, name, *args):
Yuya Nishihara
pycompat: extract function that converts attribute or encoding name to str...
r30032 return f(object, sysstr(name), *args)
Yuya Nishihara
py3: provide (del|get|has|set)attr wrappers that accepts bytes...
r29799 return w
Yuya Nishihara
py3: import builtin wrappers automagically by code transformer...
r29800 # these wrappers are automagically imported by hgloader
Yuya Nishihara
py3: provide (del|get|has|set)attr wrappers that accepts bytes...
r29799 delattr = _wrapattrfunc(builtins.delattr)
getattr = _wrapattrfunc(builtins.getattr)
hasattr = _wrapattrfunc(builtins.hasattr)
setattr = _wrapattrfunc(builtins.setattr)
Yuya Nishihara
py3: import builtin wrappers automagically by code transformer...
r29800 xrange = builtins.range
Yuya Nishihara
py3: provide (del|get|has|set)attr wrappers that accepts bytes...
r29799
Yuya Nishihara
pycompat: extract function that converts attribute or encoding name to str...
r30032 else:
def sysstr(s):
return s
Martijn Pieters
pycompat: only accept a bytestring filepath in Python 2
r30133 # Partial backport from os.py in Python 3, which only accepts bytes.
# In Python 2, our paths should only ever be bytes, a unicode path
# indicates a bug.
def fsencode(filename):
if isinstance(filename, str):
return filename
Martijn Pieters
py3: add an os.fsencode backport to ease path handling
r30119 else:
Martijn Pieters
pycompat: only accept a bytestring filepath in Python 2
r30133 raise TypeError(
"expect str, not %s" % type(filename).__name__)
Martijn Pieters
py3: add an os.fsencode backport to ease path handling
r30119
Pulkit Goyal
py3: add os.fsdecode() as pycompat.fsdecode()...
r30300 # In Python 2, fsdecode() has a very chance to receive bytes. So it's
# better not to touch Python 2 part as it's already working fine.
def fsdecode(filename):
return filename
Pulkit Goyal
py3: add a bytes version of os.name...
r30302 osname = os.name
Pulkit Goyal
py3: have pycompat.ospathsep and pycompat.ossep...
r30303 ospathsep = os.pathsep
ossep = os.sep
Pulkit Goyal
py3: add a bytes version of os.name...
r30302
Pulkit Goyal
pycompat: make pycompat demandimport friendly...
r29584 stringio = io.StringIO
timeless
pycompat: add empty and queue to handle py3 divergence...
r28818 empty = _queue.Empty
queue = _queue.Queue
timeless
pycompat: alias xrange to range in py3
r28834
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 class _pycompatstub(object):
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 def __init__(self):
self._aliases = {}
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 def _registeraliases(self, origin, items):
"""Add items that will be populated at the first access"""
Augie Fackler
pycompat: when setting attrs, ensure we use sysstr...
r30086 items = map(sysstr, items)
self._aliases.update(
(item.replace(sysstr('_'), sysstr('')).lower(), (origin, item))
for item in items)
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 def __getattr__(self, name):
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 try:
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 origin, item = self._aliases[name]
except KeyError:
raise AttributeError(name)
self.__dict__[name] = obj = getattr(origin, item)
return obj
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882
Pulkit Goyal
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import...
r29566 httpserver = _pycompatstub()
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 urlreq = _pycompatstub()
urlerr = _pycompatstub()
Yuya Nishihara
pycompat: provide 'ispy3' constant...
r30030 if not ispy3:
Pulkit Goyal
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import...
r29566 import BaseHTTPServer
import CGIHTTPServer
import SimpleHTTPServer
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 import urllib2
import urllib
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 urlreq._registeraliases(urllib, (
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 "addclosehook",
"addinfourl",
"ftpwrapper",
"pathname2url",
"quote",
"splitattr",
"splitpasswd",
"splitport",
"splituser",
"unquote",
"url2pathname",
"urlencode",
))
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 urlreq._registeraliases(urllib2, (
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 "AbstractHTTPHandler",
"BaseHandler",
"build_opener",
"FileHandler",
"FTPHandler",
"HTTPBasicAuthHandler",
"HTTPDigestAuthHandler",
"HTTPHandler",
"HTTPPasswordMgrWithDefaultRealm",
"HTTPSHandler",
"install_opener",
"ProxyHandler",
"Request",
"urlopen",
))
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 urlerr._registeraliases(urllib2, (
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 "HTTPError",
"URLError",
))
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 httpserver._registeraliases(BaseHTTPServer, (
Pulkit Goyal
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import...
r29566 "HTTPServer",
"BaseHTTPRequestHandler",
))
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 httpserver._registeraliases(SimpleHTTPServer, (
Pulkit Goyal
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import...
r29566 "SimpleHTTPRequestHandler",
))
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 httpserver._registeraliases(CGIHTTPServer, (
Pulkit Goyal
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import...
r29566 "CGIHTTPRequestHandler",
))
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 else:
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 import urllib.request
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 urlreq._registeraliases(urllib.request, (
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 "AbstractHTTPHandler",
"addclosehook",
"addinfourl",
"BaseHandler",
"build_opener",
"FileHandler",
"FTPHandler",
"ftpwrapper",
"HTTPHandler",
"HTTPSHandler",
"install_opener",
"pathname2url",
"HTTPBasicAuthHandler",
"HTTPDigestAuthHandler",
Gregory Szorc
pycompat: add HTTPPasswordMgrWithDefaultRealm to Python 3 block...
r29414 "HTTPPasswordMgrWithDefaultRealm",
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 "ProxyHandler",
"quote",
"Request",
"splitattr",
"splitpasswd",
"splitport",
"splituser",
"unquote",
"url2pathname",
"urlopen",
))
import urllib.error
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 urlerr._registeraliases(urllib.error, (
timeless
pycompat: add util.urlerr util.urlreq classes for py3 compat...
r28882 "HTTPError",
"URLError",
))
Pulkit Goyal
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import...
r29566 import http.server
Yuya Nishihara
pycompat: delay loading modules registered to stub...
r29801 httpserver._registeraliases(http.server, (
Pulkit Goyal
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import...
r29566 "HTTPServer",
"BaseHTTPRequestHandler",
"SimpleHTTPRequestHandler",
"CGIHTTPRequestHandler",
))