-
June 23rd, 2011, 07:43 AM
#1
Linux C shared libraries question
Hi,
I'm experiencing a rather unusual situation that isn't making sense to me. I'm not as familiar with linux's shared library mechanisms as I perhaps should be. This code was stripped down from a much larger project, so it'll look a little strange, but it easily demonstrates the questions I'll ask at the bottom on this:
Here is the script I am using to compile this test:
Code:
#!/bin/sh
clear
export DEF="-D_USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE"
export SRC="-D_REENTRANT -D_BSD_SOURCE"
export OPT="-w -O3 -march=i686 -mtune=i686 -ffast-math -funroll-loops -fno-exceptions -minline-all-stringops"
gcc -c -o test.o test.c $DEF $SRC $OPT
ar rcs libtest.a test.o
gcc -fPIC -c -o test.o test.c $DEF $SRC $OPT
gcc -shared -Wl,-soname,libtest.so.1 -o libtest.so.1.0.0 test.o -lc
ldconfig -n .
export DEF="-D_USE_LARGEFILE64 -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE"
export SRC="-D_REENTRANT -D_BSD_SOURCE"
export SHLIB="-ltest -L."
export OPT="-w -O3 -march=i686 -mtune=i686 -ffast-math -funroll-loops -fno-exceptions -minline-all-stringops"
gcc -o StrICmpTest StrICmpTest.c $DEF $SRC $SHLIB $OPT
Here is my test library code - test.c:
Code:
#include <stdio.h>
#define C unsigned char
#define D double
#define F float
#define I int
#define L long
#define UL2 unsigned long long
#define L2 long long
#define LD long double
#define S struct
#define SC signed char
#define SI signed int
#define STR string
#define U union
#define UC unsigned char
#define UI unsigned int
#define UL unsigned long
#define US unsigned short
#define V void
#define dStrIsLower(c) (c>='a'&&c<='z')
#define dStrIsUpper(c) (c>='A'&&c<='Z')
#define dStrToLower(c) (dStrIsUpper(c)?c-'a'-'A':c)
#define dStrToUpper(c) (dStrIsLower(c)?c+'a'-'A':c)
I stricmp7(C *s1, C *s2)
{
UL i, l1, l2, m;
C d1, d2;
l1=strlen(s1);
l2=strlen(s2);
m=l1<l2?l1:l2;
if(l1!=l2)
return(l1-l2);
for(i=0;i<m;i++)
{
d1=dStrToLower(s1[i]);
d2=dStrToLower(s2[i]);
if(d1!=d2)
return(d1-d2);
}
return(0);
}
The main program - StrICmpTest.c:
Code:
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#define MEGABYTE 1048576
typedef unsigned char string[256];
#define C unsigned char
#define D double
#define F float
#define I int
#define L long
#define UL2 unsigned long long
#define L2 long long
#define LD long double
#define S struct
#define SC signed char
#define SI signed int
#define STR string
#define U union
#define UC unsigned char
#define UI unsigned int
#define UL unsigned long
#define US unsigned short
#define V void
#define dStrIsLower(c) (c>='a'&&c<='z')
#define dStrIsUpper(c) (c>='A'&&c<='Z')
#define dStrToLower(c) (dStrIsUpper(c)?c-'a'-'A':c)
#define dStrToUpper(c) (dStrIsLower(c)?c+'a'-'A':c)
#define NFACTOR 3072
#define NTIMES (NFACTOR*NFACTOR)
I stricmp1(C *s1, C *s2)
{
UL i, l1, l2, m;
C d1, d2;
l1=strlen(s1);
l2=strlen(s2);
m=l1<l2?l1:l2;
if(l1!=l2)
return(l1-l2);
for(i=0;i<m;i++)
{
d1=dStrToLower(s1[i]);
d2=dStrToLower(s2[i]);
if(d1!=d2)
return(d1-d2);
}
return(0);
}
I main(I argc, C *argv[])
{
clock_t st, et;
STR buffer;
I i, l1;
strcpy(buffer,"Hello World ABCDEFGHIJKLMNOPQRSTUVWXYZ");
st=clock();
for(i=0;i<NTIMES;i++) {
l1=strcasecmp(buffer,buffer);
l1=strcasecmp(buffer,"Hello World ABCDEFGHIJKLMNOPQRSTUVWXYZ Kitty"); }
et=clock();
printf("strcasecmp, %f\n",((D)(et-st))/((D)CLOCKS_PER_SEC));
st=clock();
for(i=0;i<NTIMES;i++) {
l1=stricmp1(buffer,buffer);
l1=stricmp1(buffer,"Hello World ABCDEFGHIJKLMNOPQRSTUVWXYZ Kitty"); }
et=clock();
printf("stricmp1, %f\n",((D)(et-st))/((D)CLOCKS_PER_SEC));
st=clock();
for(i=0;i<NTIMES;i++) {
l1=stricmp7(buffer,buffer);
l1=stricmp7(buffer,"Hello World ABCDEFGHIJKLMNOPQRSTUVWXYZ Kitty"); }
et=clock();
printf("stricmp7, %f\n",((D)(et-st))/((D)CLOCKS_PER_SEC));
return(0);
}
Now for the output:
Code:
./MKTlib && ./StrICmpTest
strcasecmp, 0.000000
stricmp1, 0.020000
stricmp7, 1.910000
As you can see, the program runs perfectly. I'm using a full and clean install of Slackware 13.1, gcc version of 4.4.4
Now for the questions:
1. Why does stricmp7 take so much longer to run then stricmp1 when the code of both is identical?
Code:
ldd StrICmpTest
linux-gate.so.1 => (0xb7794000)
libc.so.6 => /lib/libc.so.6 (0xb761b000)
/lib/ld-linux.so.2 (0xb7795000)
2. Why does libtest NOT show up in the above?
3. What can be done to fix this problem?
Thank you in advance.
-
June 24th, 2011, 07:55 AM
#2
Originally Posted by frpeter
1. Why does stricmp7 take so much longer to run then stricmp1 when the code of both is identical?
You used different compiler options.
Oliver's Law:
Experience is something you don't get until just after you need it.
-
June 24th, 2011, 09:09 AM
#3
Hi,
Originally Posted by SirDice
You used different compiler options.
I must be dense as I'm not understanding where the options are different. I specified the below options for both the library and the main code:
-w -O3 -march=i686 -mtune=i686 -ffast-math -funroll-loops -fno-exceptions
-minline-all-stringops
Are there different options required for the library to be properly optimized?
Thanks.
-
June 29th, 2011, 07:56 AM
#4
No, you're right. I'm the one that's being dense.
It might be because of the overhead though. The library needs to be loaded and initialized before it's used. The built-in function obviously doesn't.
See what happens if you execute both functions multiple times. I'm sure the times will converge more as the overhead of loading the library only happens once.
Oliver's Law:
Experience is something you don't get until just after you need it.
-
June 30th, 2011, 08:59 AM
#5
Originally Posted by SirDice
It might be because of the overhead though. The library needs to be loaded and initialized before it's used. The built-in function obviously doesn't.
See what happens if you execute both functions multiple times. I'm sure the times will converge more as the overhead of loading the library only happens once.
I actually tried this several times against strcasecmp thinking the same thing, but I didn't get the same results with the standard library as you'll see in the example I provided. I know the standard library is optimized in assembly, but the load time should still be a factor with the standard library as with my test library.
I repeated the tests several hundred times with and without debugging turned on as well as a myriad of different compiler options and even on a different linux platform seeing if I had a broken linker trying to trace this. The timing of my test library actually behaves as if debugging is turned on even though it isn't. I also did an strace and gprof to see if anything unusual showed up. Everything went as one would expect.
The timing difference is relatively small, usually on the order of 0.01 to 0.05 ms... I do need to post the code over as I noticed a few typos, but those have no baring on the load and run times of the library.
Thanks.
Similar Threads
-
By gore in forum Operating Systems
Replies: 83
Last Post: June 1st, 2017, 01:33 PM
-
By rider_royal in forum Newbie Security Questions
Replies: 25
Last Post: July 3rd, 2005, 10:43 AM
-
By pwaring in forum Other Tutorials Forum
Replies: 60
Last Post: October 22nd, 2004, 09:15 PM
-
By gore in forum Other Tutorials Forum
Replies: 6
Last Post: October 5th, 2004, 08:26 AM
-
By gore in forum Operating Systems
Replies: 3
Last Post: March 7th, 2004, 08:02 AM
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
|