develooper Front page | perl.perl5.porters | Postings from May 2004

[perl #29637] Thread creation time is hypersensitive

Thread Previous | Thread Next
From:
Jamie Lokier
Date:
May 17, 2004 01:43
Subject:
[perl #29637] Thread creation time is hypersensitive
Message ID:
rt-3.0.9-29637-87553.11.6565004757339@perl.org
# New Ticket Created by  Jamie Lokier 
# Please include the string:  [perl #29637]
# in the subject line of all future correspondence about this issue. 
# <URL: http://rt.perl.org:80/rt3/Ticket/Display.html?id=29637 >



This is a bug report for perl from jamie@shareable.org,
generated with the help of perlbug 1.34 running under perl v5.8.0.


-----------------------------------------------------------------
[Please enter your report here]

Please take the time to read this report carefully, as it appears to
be a Perl ithreads bug which, if fixed, would probably improve thread
creation time substantially in all cases - and it's probably a simple
logic error in the threading code.

The time to create a new thread is highly sensitive to conditions that
shouldn't affect the time.

Adding a single short, semantically void comment line to a large
script can _quadruple_ the time to create new threads in that script
for example.  Or it can have the opposite effect: adding a comment
line can reduce the time by a similar factor.  Many other changes have
a similar effect.

The effect is repeatable: a script which starts threads slowly does so
each time the program is run.  Similarly for scripts which start
threads quickly.

It is also sensitive to names: changing the name of some modules in
tests removes the effect - effectively changing the boundary
condition which highlights it.

The time variation is accompanied by variation in the amount of memory
allocated when creating a thread.  "strace" shows that slow thread
creation is accompanied by more mmap() calls to allocate memory.  In
fact most of the thread creation time appears to be spent allocating
memory in tiny mmap() calls.

There's strong evidence that this is a Perl bug, not a libc thread
creation bug.  "strace" shows a very large number of 4k mmap() calls
to allocate memory on each thread creation.  For one, this is silly
and slow: pages should be allocated many at a time, and handed out
within the program, not using thousands of small mmap() calls.  For
two, the enormous variation in thread creation times is matched with
variation in the number of single-page mmap() calls from Perl.  This
implies that Perl's own allocation and copying logic for non-shared
data is not behaving as intended.

I have tried to produce examples of two Perl programs which differ
only by a few comment characters and exhibit a large difference in
thread creation time.  I succeeded, with one taking ~40ms per thread
and the other taking ~150ms per thread, but the programs consist of
several large modules, derived from a real program when I first
noticed the problem, and trimming the code down is difficult because
the condition is so sensitive to the numbers of characters in each
file, the number of functions and variables created and their names etc.

That's why I haven't included example code.  If there's a need for it,
I can supply a set of files privately, but I think there's a chance
the bug can be diagnosed from this description alone.

I noticed this problem when trying to speed up a script which uses
threads, and takes about 2 seconds to create each new thread on a
1.5GHz x86.  I saw that the script uses modules which are slow to
load, "IO::Socket::INET" in particular.  I guessed that loading big
modules would slow down thread creation because of the copying
(although 2 seconds is a remarkably long time for copying anything).

So I removed references to all IO::* modules, and it made the script
much faster.  I removed more modules, it helped some more.  I thought
I had understood the problem.  Then imagine my surprise when I
commented _out_ a line saying "use Fcntl" and thread creation became
much slower again!  With some more experimentation, I discovered
thread creation time is only partly to do with the modules loaded, and
much of the time, when it's slow, is caused by this hypersensitive
effect which is accompanied by large numbers of mmap() calls.
Unfortunately I haven't found a coding strategy to avoid the effect
and get consistently fast thread creation.  The only way to get that
is to fix the Perl core - which is a bit too much for me.

Thanks,
-- Jamie

[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
    category=core
    severity=high
---
Site configuration information for perl v5.8.0:

Configured by bhcompile'
cf_email='bhcompile at Wed Aug 13 11:45:59 EDT 2003.

Summary of my rderl (revision 5.0 version 8 subversion 0) configuration:
  Platform:
    osname=linux, osvers=2.4.21-1.1931.2.382.entsmp, archname=i386-linux-thread-multi
    uname='linux str'
    config_args='-des -Doptimize=-O2 -g -pipe -march=i386 -mcpu=i686 -Dmyhostname=localhost -Dperladmin=root@localhost -Dcc=gcc -Dcf_by=Red Hat, Inc. -Dinstallprefix=/usr -Dprefix=/usr -Darchname=i386-linux -Dvendorprefix=/usr -Dsiteprefix=/usr -Dotherlibdirs=/usr/lib/perl5/5.8.0 -Duseshrplib -Dusethreads -Duseithreads -Duselargefiles -Dd_dosuid -Dd_semctl_semun -Di_db -Ui_ndbm -Di_gdbm -Di_shadow -Di_syslog -Dman3ext=3pm -Duseperlio -Dinstallusrbinperl -Ubincompat5005 -Uversiononly -Dpager=/usr/bin/less -isr'
    hint=recommended, useposix=true, d_sigaction=define
    usethreads=define use5005threads=undef'
 useithreads=define usemultiplicity=
    useperlio= d_sfio=undef uselargefiles=define usesocks=undef
    use64bitint=undef use64bitall=un uselongdouble=
    usemymalloc=, bincompat5005=undef
  Compiler:
    cc='gcc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm',
    optimize='',
    cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBUGGING -fno-strict-aliasing -I/usr/local/include -I/usr/include/gdbm'
    ccversion='', gccversion='3.2.2 20030222 (Red Hat Linux 3.2.2-5)', gccosandvers=''
gccversion='3.2.2 200302'
    intsize=r, longsize=r, ptrsize=5, doublesize=8, byteorder=1234
    d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
    ivtype='long'
k', ivsize=4'
ivtype='l, nvtype='double'
o_nonbl', nvsize=, Off_t='', lseeksize=8
    alignbytes=4, prototype=define
  Linker and Libraries:
    ld='gcc'
l', ldflags =' -L/u'
    libpth=/usr/local/lib /lib /usr/lib
    libs=-lnsl -lgdbm -ldb -ldl -lm -lpthread -lc -lcrypt -lutil
    perllibs=
    libc=/lib/libc-2.3.2.so, so=so, useshrplib=true, libperl=libper
    gnulibc_version='2.3.2'
  Dynamic Linking:
    dlsrc=dl_dlopen.xs, dlext=so', d_dlsymun=undef, ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5/5.8.0/i386-linux-thread-multi/CORE'
    cccdlflags='-fPIC'
ccdlflags='-rdynamic -Wl,-rpath,/usr/lib/perl5', lddlflags='s Unicode/Normalize XS/A'

Locally applied patches:
    MAINT18379

---
@INC for perl v5.8.0:
    /usr/lib/perl5/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/5.8.0
    /usr/lib/perl5/site_perl/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/site_perl/5.8.0
    /usr/lib/perl5/site_perl
    /usr/lib/perl5/vendor_perl/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/vendor_perl/5.8.0
    /usr/lib/perl5/vendor_perl
    /usr/lib/perl5/5.8.0/i386-linux-thread-multi
    /usr/lib/perl5/5.8.0
    .

---
Environment for perl v5.8.0:
    HOME=/home/jamie
    LANG=en_GB.UTF-8
    LANGUAGE (unset)
    LD_LIBRARY_PATH (unset)
    LOGDIR (unset)
    PATH=/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/home/jamie/bin
    PERL_BADLANG (unset)
    SHELL=/bin/bash
    dlflags='-share (unset)


Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About