기본 콘텐츠로 건너뛰기

새로운 노트북

공유객체 속도

UNIX 공유객체(shared object) 만들기

테스트 환경을 만들기 전에 파일명을 소개하겠다.
  • Makefile - 빌드를 위한 스크립트
  • plgn.cpp - plgn.so를 위한 소스. func2 함수가 포함되어 있다.
  • sotest.cpp - 시간 측정을 위한 소스. func1 함수가 포함되어 있다.
일단 Makefile
TARGET=sotest plgn.so
CXXFLAGS=-g -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT
LDFLAGS=-ldl

all:$(TARGET)

clean:
    $(RM) $(TARGET) *.o

sotest:sotest.cpp

plgn.so:plgn.o
    $(CXX) $(CXXFLAGS) -shared -lc -o $@ $<

plgn.o:plgn.cpp
    $(CXX) $(CXXFLAGS) -c -fPIC $<
뭐, 대충 흉내만 내놓고... 다음은 plgn.cpp
extern "C" void func2(volatile int*);

void
func2(volatile int* v)
{
    ++(*v);
}
역시나 흉내내기. extern "C"를 붙여 맹글링 회피 능력을 +3 했다. (뻘소리)
다음은 sotest.cpp
#include <iostream>
#include <dlfcn.h>
#include <sys/time.h>
using namespace std;

static const size_t testcount(1000000UL);

long long
getTimestamp(void)
{
    static struct timeval tv;
    gettimeofday(&tv, NULL);
    return 1000000LL*tv.tv_sec+tv.tv_usec;
}

extern "C" void func1(volatile int*);

typedef void (*func_t) (volatile int*);

void
func1
(volatile int* i)
{
    ++(*i);
}

void
testFunc(func_t f, const char* msg)
{
    static const long long t1(getTimestamp());
    volatile int v(0);
    for ( size_t i(0); i<testcount; i++ )
    {
        f(&v);
    }
    cout << msg << ": " << (getTimestamp()-t1)/1000.0 << " msec" << endl;
}

void
testSFunc(int flag, const char* msg)
{
    static void* handle(NULL);
    handle = dlopen("./plgn.so", flag);
    if ( !handle )
    {
        cout << dlerror() << endl;
        return;
    }

    int tip;
    func_t f((func_t)dlsym(handle,"func2"));
    f(&tip);
    testFunc(f, msg);
    dlclose(handle);
    handle = NULL;
}

int
main(int,char**)
{
    testFunc(func1,"Local");
    testSFunc(RTLD_LAZY|RTLD_LOCAL, "Shared(LAZY|LOCAL)");
    testSFunc(RTLD_NOW|RTLD_LOCAL, "Shared(NOW|LOCAL)");
    testSFunc(RTLD_LAZY|RTLD_GLOBAL, "Shared(LAZY|GLOBAL)");
    testSFunc(RTLD_NOW|RTLD_GLOBAL, "Shared(NOW|GLOBAL)");

    return 0;
}
자, 빌드해보자.
$make
g++ -g -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT -ldl sotest.cpp -o sotest
g++ -g -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT -c -fPIC plgn.cpp
g++ -g -O2 -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT -shared -lc -o plgn.so plgn.o
실행 결과는?
$ ./sotest
Local: 3.496 msec
Shared(LAZY|LOCAL): 7.221 msec
Shared(NOW|LOCAL): 10.786 msec
Shared(LAZY|GLOBAL): 14.349 msec
Shared(NOW|GLOBAL): 17.908 msec
느리구나... -_- 두 배나...

댓글

이 블로그의 인기 게시물

Bash Array, Map 정리

Bash에서 Array, Map에 대한 정리. (매번 찾기 귀찮) 찾아보진 않았지만, Bash에서 Array든 Map이든 동일하게 Map(C++에서 Unordered Map)으로 동작하는 것 같다. 왜냐하면, Array의 Index가 연속하지 않아도 동작한다. 그저 Key가 0 이상의 정수인 Map이랑 비슷하게 동작한다. 예) 1, 2, 3, 9, 10 Array # 생성 declare -a empty_array declare -a ar=(haha hoho baba "long string haha hoho") # 접근 echo "ar[0]=${ar[0]}" echo "all as array=${ar[@]}" # 큰따옴표 안에서 각 원소를 따로따로 전달한다. echo "all as one=${ar[*]}" # 큰따옴표 안에서 각 원소를 문자열 하나로 합쳐 전달한다. echo "indexes=${!ar[@]}" echo "indexes=${!ar[*]}" echo "length=${#ar[@]}" echo "length=${#ar[*]}" echo "last=${ar[-1]}" echo "last=${ar[@]: -1}" # 콜론 뒤에 빈 칸이 꼭 필요하다. 옛 방식 # 현재 상황 declare -p ar #(출력) declare -a ar=([0]="haha" [1]="hoho" [2]="baba" [3]="long string haha hoho") ar[100]=hello # 인덱스를 건너 뛰어도 동작한다. declare -p ar #(출력) declare -a ar=([0]="haha" [1]="hoho" [2]="baba" [3]=&

설치한 패키지에서 RPM 추출하기

오래된 패키지를 관리할 저장소가 없어졌고, 기존 패키지로 다른 서버를 세팅해야할 일이 생겼다면 RPM의 리패키지 기능을 이용해보자. $ rpm -e --repackage [PACKAGE_NAME] 위와 같이 리패키지하면, /var/spool/repackage/ 에 생성한 RPM파일이 있다. :-)