Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Numeric comparison $! == EXXX does expensive locale operations #7345

Closed
p5pRT opened this issue Jun 6, 2004 · 7 comments
Closed

Numeric comparison $! == EXXX does expensive locale operations #7345

p5pRT opened this issue Jun 6, 2004 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Jun 6, 2004

Migrated from rt.perl.org#30076 (status was 'resolved')

Searchable as RT30076$

@p5pRT
Copy link
Author

p5pRT commented Jun 6, 2004

From @jlokier

Created by @jlokier

When I evaluate $! in a numeric context in order to do a simple
comparison, strace shows that significant locale string operations are
performed.

Specifically, in code which does this​:

  $n = sysread ($socket, $buffer, $length, $offset);
  if (!defined $n && $! == EAGAIN) {
  # Do some stuff
  }

The comparison $! == EAGAIN should be fast. However, strace shows
that system message catalogues are searched the first time that call
is made.

I guess that is because evaluating $! looks up the text corresponding
to the error, by calling strerror(), even though the text isn't needed
in a numerical context. strerror() does a locale message translation.

Subsequent uses of $! don't show anything in strace, however this is
enough evidence to indicate that Perl is calling strerror() whenever a
$! value is looked up for the first time after being set -- and that
is still potentially a slow operation if libc's strerror() is slow
with a locale.

The obvious fix is to change $! so it doesn't do a string operation
when it's read in a numerical context.

A workaround is to set the locale to the C locale, but that has
undesirable side effects if you actually want to display error texts
in other parts of the program -- and (I guess) it probably doesn't
eliminate the calls to strerror(), just they become faster.

-- Jamie

Perl Info

Flags:
    category=core
    severity=medium

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)

@p5pRT
Copy link
Author

p5pRT commented Jun 8, 2004

From @iabyn

On Sun, Jun 06, 2004 at 10​:48​:02PM -0000, Jamie Lokier wrote​:

When I evaluate $! in a numeric context in order to do a simple
comparison, strace shows that significant locale string operations are
performed.

Specifically, in code which does this​:

$n = sysread \($socket\, $buffer\, $length\, $offset\);
if \(\!defined $n && $\! == EAGAIN\) \{
    \# Do some stuff
\}

The comparison $! == EAGAIN should be fast. However, strace shows
that system message catalogues are searched the first time that call
is made.

I can't reproduce this. Do you have a small standalone script that
demonstrates this? This is what I've tried so far​:

  use Errno qw(EAGAIN);
  print "about to compare\n";
  my $x = ($! == EAGAIN);

$ LANG=en_GB.UTF-8 strace perl580 /tmp/p
.....
write(1, "about to compare\n", 17about to compare
) = 17
munmap(0x40026000, 4096) = 0
_exit(0) = ?

--
Never do today what you can put off till tomorrow.

@p5pRT
Copy link
Author

p5pRT commented Jun 8, 2004

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Jun 9, 2004

From @jlokier

Dave Mitchell via RT wrote​:

I can't reproduce this. Do you have a small standalone script that
demonstrates this? This is what I've tried so far​:

use Errno qw\(EAGAIN\);
print "about to compare\\n";
my $x = \($\! == EAGAIN\);

$ LANG=en_GB.UTF-8 strace perl580 /tmp/p
.....
write(1, "about to compare\n", 17about to compare
) = 17
munmap(0x40026000, 4096) = 0
_exit(0) = ?

Put "close BAD;" before the print statement. It'll cause an EBADF error.
The locale stuff happens after the print statement.

-- Jamie

@p5pRT
Copy link
Author

p5pRT commented Jun 9, 2004

From @gbarr

On 9 Jun 2004, at 00​:44, Dave Mitchell wrote​:

On Sun, Jun 06, 2004 at 10​:48​:02PM -0000, Jamie Lokier wrote​:

When I evaluate $! in a numeric context in order to do a simple
comparison, strace shows that significant locale string operations are
performed.

Specifically, in code which does this​:

$n = sysread \($socket\, $buffer\, $length\, $offset\);
if \(\!defined $n && $\! == EAGAIN\) \{
    \# Do some stuff
\}

The comparison $! == EAGAIN should be fast. However, strace shows
that system message catalogues are searched the first time that call
is made.

I can't reproduce this. Do you have a small standalone script that
demonstrates this? This is what I've tried so far​:

use Errno qw\(EAGAIN\);
print "about to compare\\n";
my $x = \($\! == EAGAIN\);

I can, but with

  $! = 1;
  my $x = ($! == 1);

The reason for this is that when the magic is called to populate the SV
with errno and errno is not zero then a dualvar is created by
populating both the IV and PV parts of the SV. To populate the PV we
must call strerror(3) which is likely to be what is causing these
calls.

Graham.

@p5pRT p5pRT closed this as completed Jun 14, 2004
@p5pRT
Copy link
Author

p5pRT commented Jun 14, 2004

@rgs - Status changed from 'open' to 'resolved'

@p5pRT
Copy link
Author

p5pRT commented Jun 14, 2004

From @jlokier

Rafael Garcia-Suarez via RT wrote​:

According to our records, your request regarding
"Numeric comparison $! == EXXX does expensive locale operations"
has been resolved.

How has it been resolved?

It's been confirmed, and the cause isolated - but that was already
known in the initial bug report.

Doesn't resolved imply it's either fixed or won't be fixed?

I didn't see anything attached to this bug which indicates either.

Thanks,
-- Jamie

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant