[PATCH 2 of 2] osutil.c: replace alloca() with malloc() and remove <alloca.h>

Giorgos Keramidas keramida at ceid.upatras.gr
Sun Oct 7 18:03:47 CDT 2007


On 2007-10-07 23:56, Benoit Boissinot <benoit.boissinot at ens-lyon.org> wrote:
>On Mon, Oct 08, 2007 at 12:43:09AM +0300, Giorgos Keramidas wrote:
>>On 2007-10-07 23:26, Benoit Boissinot <bboissin at gmail.com> wrote:
>>>On 10/7/07, Giorgos Keramidas <keramida at ceid.upatras.gr> wrote:
>>>> The <alloca.h> header is not really portable, and it breaks Mercurial on
>>>> FreeBSD.  Remove the dependency on <alloca.h> and alloca() by replacing
>>>> the only place where it was used with malloc().
>>>
>>> Have you done a performance test to see wether it has an impact or not ?
>>
>> Not really, how should I go about testing that this is not a performance
>> regression?  I ssuspect there's going to be a minor overhead because of
>> an extra function call for the free() I added, but it would be nice to
>> be able to produce useful performance test results.
>
> hg status on a huge repo ?

Interesting results.

After adding <stdlib.h> the mercurial/osutil.c file compiles correctly
either with alloca() or malloc(), so I used this to run "hg --lsprof
stat" and "hg --profile stat" on a snapshot of the FreeBSD src/ tree,
with around 37000 files:

% keramida at kobe:/home/keramida/hg/freebsd/head> hg manif | wc -l
%    37322
% keramida at kobe:/home/keramida/hg/freebsd/head>

The results are attached as four files:

% hg-lsprof-alloca.txt    ; output of "hg --lsprof stat" with alloca()
% hg-lsprof-malloc.txt    ; output of "hg --lsprof stat" with malloc()
% hg-profile-alloca.txt   ; output of "hg --profile stat" with alloca()
% hg-profile-malloc.txt   ; output of "hg --profile stat" with malloc()

Running "diff -u /tmp/hg-lsprof*" produces no output.  So the change
from malloc() to alloca() and vice versa is not visibly different here.

The results of "hg --profile" are a bit interesting, however.  The
version of osutil.c which uses malloc() seems to be a bit faster, which
is odd :-/

For example, this part is rather odd (alloca = '-', malloc = '+'):

% --- hg-profile-alloca.txt       2007-10-08 01:52:39.000000000 +0300
% +++ hg-profile-malloc.txt       2007-10-08 01:54:08.000000000 +0300
% @@ -1,49 +1,49 @@
%  ? hg.prof
% -         394369 function calls (394323 primitive calls) in 7.126 CPU seconds
% +         394369 function calls (394323 primitive calls) in 6.742 CPU seconds
%
%     Ordered by: internal time, call count
%     List reduced from 67 to 40 due to restriction <40>
%
%     ncalls  tottime  percall  cumtime  percall filename:lineno(function)
% -        1    4.900    4.900    6.087    6.087 dirstate.py:404(findfiles)
% -    83039    0.428    0.000    0.428    0.000 posixpath.py:56(join)
% -        1    0.352    0.352    0.578    0.578 dirstate.py:124(_read)
% -        1    0.250    0.250    7.122    7.122 dirstate.py:493(status)
% -    37322    0.221    0.000    0.221    0.000 struct.py:77(unpack)
% -    37324    0.198    0.000    6.292    0.000 dirstate.py:352(statwalk)
% -    37323    0.171    0.000    0.240    0.000 dirstate.py:376(imatch)
% -    37323    0.159    0.000    0.379    0.000 dirstate.py:333(_supported)
% -    37323    0.152    0.000    0.220    0.000 stat.py:54(S_ISREG)
% -    41518    0.075    0.000    0.075    0.000 util.py:1131(pconvert)
% -    37323    0.069    0.000    0.069    0.000 util.py:252(always)
% +        1    4.617    4.617    5.755    5.755 dirstate.py:404(findfiles)
% +    83039    0.407    0.000    0.407    0.000 posixpath.py:56(join)
% +        1    0.334    0.334    0.541    0.541 dirstate.py:124(_read)
% +        1    0.240    0.240    6.738    6.738 dirstate.py:493(status)
% +    37322    0.200    0.000    0.200    0.000 struct.py:77(unpack)
% +    37324    0.194    0.000    5.954    0.000 dirstate.py:352(statwalk)
% +    37323    0.167    0.000    0.233    0.000 dirstate.py:376(imatch)
% +    37323    0.153    0.000    0.365    0.000 dirstate.py:333(_supported)
% +    37323    0.144    0.000    0.212    0.000 stat.py:54(S_ISREG)
% +    41518    0.073    0.000    0.073    0.000 util.py:1131(pconvert)

This may be an artifact of the malloc() and alloca() implementation of
FreeBSD, so I'll run the same test on Linux and Solaris and report back
tomorrow; I don't have access to a Solaris machine now :(

In the mean time, is there any other command which would be interesting
to run with --profile and --lsprof?

- Giorgos

-------------- next part --------------
? hg.prof
-------------- next part --------------
? hg.prof
-------------- next part --------------
? hg.prof
         394369 function calls (394323 primitive calls) in 7.126 CPU seconds

   Ordered by: internal time, call count
   List reduced from 67 to 40 due to restriction <40>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    4.900    4.900    6.087    6.087 dirstate.py:404(findfiles)
    83039    0.428    0.000    0.428    0.000 posixpath.py:56(join)
        1    0.352    0.352    0.578    0.578 dirstate.py:124(_read)
        1    0.250    0.250    7.122    7.122 dirstate.py:493(status)
    37322    0.221    0.000    0.221    0.000 struct.py:77(unpack)
    37324    0.198    0.000    6.292    0.000 dirstate.py:352(statwalk)
    37323    0.171    0.000    0.240    0.000 dirstate.py:376(imatch)
    37323    0.159    0.000    0.379    0.000 dirstate.py:333(_supported)
    37323    0.152    0.000    0.220    0.000 stat.py:54(S_ISREG)
    41518    0.075    0.000    0.075    0.000 util.py:1131(pconvert)
    37323    0.069    0.000    0.069    0.000 util.py:252(always)
    37324    0.068    0.000    0.068    0.000 stat.py:29(S_IFMT)
     4196    0.057    0.000    0.057    0.000 posixpath.py:373(normpath)
     4195    0.008    0.000    0.008    0.000 util.py:253(never)
    11/10    0.007    0.001    0.013    0.001 demandimport.py:43(_load)
       18    0.006    0.000    0.006    0.000 demandimport.py:80(_demandimport)
        4    0.003    0.001    0.582    0.146 dirstate.py:27(__getattr__)
    55/10    0.001    0.000    0.013    0.001 demandimport.py:71(__getattribute__)
        2    0.000    0.000    0.000    0.000 util.py:1347(__call__)
        1    0.000    0.000    0.001    0.001 dirstate.py:8(<module>)
        1    0.000    0.000    0.000    0.000 ignore.py:24(ignore)
        1    0.000    0.000    7.126    7.126 commands.py:2536(status)
       13    0.000    0.000    0.000    0.000 demandimport.py:31(__init__)
        1    0.000    0.000    0.000    0.000 dirstate.py:18(dirstate)
        1    0.000    0.000    0.000    0.000 cmdutil.py:211(matchpats)
        1    0.000    0.000    7.122    7.122 localrepo.py:872(status)
        2    0.000    0.000    0.000    0.000 util.py:708(__call__)
        1    0.000    0.000    0.000    0.000 ui.py:371(write)
        1    0.000    0.000    0.000    0.000 ui.py:291(_configitems)
        1    0.000    0.000    0.003    0.003 cmdutil.py:97(revpair)
        1    0.000    0.000    7.126    7.126 dispatch.py:340(<lambda>)
        1    0.000    0.000    0.000    0.000 ConfigParser.py:527(items)
        1    0.000    0.000    0.000    0.000 struct.py:43(calcsize)
        1    0.000    0.000    0.000    0.000 dirstate.py:71(getcwd)
        1    0.000    0.000    0.000    0.000 util.py:409(cmdmatcher)
        2    0.000    0.000    0.001    0.000 dirstate.py:110(parents)
        1    0.000    0.000    0.002    0.002 localrepo.py:87(__getattr__)
        2    0.000    0.000    0.000    0.000 util.py:144(_interpolate)
        1    0.000    0.000    0.003    0.003 struct.py:27(<module>)
        1    0.000    0.000    0.000    0.000 dirstate.py:84(pathto)


-------------- next part --------------
? hg.prof
         394369 function calls (394323 primitive calls) in 6.742 CPU seconds

   Ordered by: internal time, call count
   List reduced from 67 to 40 due to restriction <40>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    4.617    4.617    5.755    5.755 dirstate.py:404(findfiles)
    83039    0.407    0.000    0.407    0.000 posixpath.py:56(join)
        1    0.334    0.334    0.541    0.541 dirstate.py:124(_read)
        1    0.240    0.240    6.738    6.738 dirstate.py:493(status)
    37322    0.200    0.000    0.200    0.000 struct.py:77(unpack)
    37324    0.194    0.000    5.954    0.000 dirstate.py:352(statwalk)
    37323    0.167    0.000    0.233    0.000 dirstate.py:376(imatch)
    37323    0.153    0.000    0.365    0.000 dirstate.py:333(_supported)
    37323    0.144    0.000    0.212    0.000 stat.py:54(S_ISREG)
    41518    0.073    0.000    0.073    0.000 util.py:1131(pconvert)
    37324    0.068    0.000    0.068    0.000 stat.py:29(S_IFMT)
    37323    0.066    0.000    0.066    0.000 util.py:252(always)
     4196    0.053    0.000    0.053    0.000 posixpath.py:373(normpath)
     4195    0.008    0.000    0.008    0.000 util.py:253(never)
    11/10    0.007    0.001    0.014    0.001 demandimport.py:43(_load)
       18    0.006    0.000    0.006    0.000 demandimport.py:80(_demandimport)
        4    0.003    0.001    0.546    0.136 dirstate.py:27(__getattr__)
    55/10    0.001    0.000    0.014    0.001 demandimport.py:71(__getattribute__)
        2    0.000    0.000    0.001    0.000 util.py:1347(__call__)
        1    0.000    0.000    0.001    0.001 dirstate.py:8(<module>)
       13    0.000    0.000    0.000    0.000 demandimport.py:31(__init__)
        1    0.000    0.000    6.742    6.742 commands.py:2536(status)
        1    0.000    0.000    0.000    0.000 ignore.py:24(ignore)
        1    0.000    0.000    0.000    0.000 cmdutil.py:211(matchpats)
        1    0.000    0.000    0.000    0.000 dirstate.py:18(dirstate)
        2    0.000    0.000    0.000    0.000 util.py:708(__call__)
        1    0.000    0.000    6.738    6.738 localrepo.py:872(status)
        1    0.000    0.000    0.000    0.000 ui.py:371(write)
        1    0.000    0.000    0.004    0.004 cmdutil.py:97(revpair)
        1    0.000    0.000    0.000    0.000 ui.py:291(_configitems)
        1    0.000    0.000    0.000    0.000 dirstate.py:71(getcwd)
        1    0.000    0.000    0.000    0.000 struct.py:43(calcsize)
        1    0.000    0.000    6.742    6.742 dispatch.py:340(<lambda>)
        1    0.000    0.000    0.000    0.000 ConfigParser.py:527(items)
        1    0.000    0.000    0.000    0.000 util.py:409(cmdmatcher)
        1    0.000    0.000    0.003    0.003 localrepo.py:87(__getattr__)
        1    0.000    0.000    0.004    0.004 struct.py:27(<module>)
        2    0.000    0.000    0.000    0.000 util.py:144(_interpolate)
        1    0.000    0.000    0.000    0.000 ui.py:305(configitems)
        2    0.000    0.000    0.001    0.000 dirstate.py:110(parents)




More information about the Mercurial-devel mailing list