레이블이 tip인 게시물을 표시합니다. 모든 게시물 표시
레이블이 tip인 게시물을 표시합니다. 모든 게시물 표시

2018년 11월 4일 일요일

std::launch::async VS ThreadPool

이번에 std::lauch::async와 ThreadPool의 성능을 간단하게 비교해 볼 일이 있었는데..

결과부터 말하면 내가 테스트한 환경에서는 ThreadPool 이 더 좋았다.

CPU를 고르게 쓴 것도 ThreadPool 쪽이 좀 더...


std::lauch::async의 cpu 사용 그래프

ThreadPool의 cpu 그래프

수행 시간은 ms 단위다
Loopstd::launch::asyncThreadPool: 6개 스레드ThreadPool: 12개 스레드
20,00029,753,41428,068,95228,290,221
20,00030,571,60127,823,25129,157,295
100,000147,357,532136,098,045141,674,844
100,000148,868,279136,130,447141,939,465

아래에서는 visual stduio 2017 환경에서 조사식의 @CLK를 활용한 수행시간 체크도 가볍게 말씀드린다.
테스트 CPU는 아래 링크해뒀다.

테스트에 사용했던 ThreadPool은 아래 링크다. 일부 변경된 상태로 테스트 했다.싱글톤 패턴을 넣었다던가, 스레드 개수를 생성자가 아니라 따로 함수를 만들어서 받으면서 시작했다던가..

std::lauch::async 테스트 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const int ThreadLoopMax = 100000;
int main(void)
{
    auto func = [&]()
    {
          // 테스트를 위한 람다 함수
    };
    // 수행시간 체크 시작하는 부분
    cout << "start" << "\n";
    for (int tLoop = 0; tLoop < ThreadLoopMax; tLoop++)
    {
        std::future<void> ret = std::async(std::launch::async, func);
        ret.get();
    }
    // 수행시간 체크 종료하는 부분
    cout << "end" << "\n";
    return 0;
}
cs

ThreadPool 테스트 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const int ThreadLoopMax = 100000;
int main(void)
{
    auto func = [&]()
    {
          // 테스트를 위한 람다 함수
    };
    // 스레드 개수 설정.
    ThreadPool::GetIns().Start(12);
    // 수행시간 체크 시작하는 부분
    cout << "start" << "\n";
    for (int tLoop = 0; tLoop < ThreadLoopMax; tLoop++)
    {
        auto ret = ThreadPool::GetIns().enqueue(func);
        ret.get();
    }
    // 수행시간 체크 종료하는 부분
    cout << "end" << "\n";
    return 0;
}
cs

여기서부터 @CLK를 통해 수행 시간을 체크하는 방법을 간략하게 소개한다.우선 체크하고자 하는 지점에 브레이크를 걸어둔다. 위의 예시로 든 코드에서는 start, end를 출력하는 부분이다.




그리고 디버그 모드로 실행하면, 조사식에 @CLK를 입력해준다.우선 start를 출력하는 시점에 브레이크가 걸리면서 해당 시점에 Clocking 값을 보여줄 것이다.



우선 지금 시점부터 수행 시간을 체크하는게 목적이므로, @CLK 값을 0으로 초기화해준다. 아래처럼..



수행하고 나서 end를 출력하는 시점에 다시 브레이크가 걸리면 조사식을 통해 @CLK값을 확인할 수 있다.
간략한 테스트에는 위 방법을 써도 좋지만, 표본이 많이 필요한 경우라면 그냥 시간 저장해서 파일로 로그를 남기던가 하는게 더 좋겠다.

2018년 10월 27일 토요일

cpp_redis 설치부터 tcp_client와 tcp_server 사용하기

음.. 이번에 Redis를 접하면서 경험했던 것들을 하나씩 정리한다.

일단 redis 설치부터 시작해서, cpp_redis 라이브러리 빌드 그리고

tcp_client와 tcp_server를 활용해 async_write, async_read 까지 테스트해본다.

언제나 그렇듯 부족하거나 틀린 부분이 있으면 지적해주시면 확인해보고 수정하겠습니다 :)



테스트 환경은 윈도우10 64비트이다.

우선 설치부터 시작해보자.

1. 아래 링크에서 .msi 파일을 다운로드하여 설치한다.
https://github.com/MicrosoftArchive/redis/releases

2. 아래 링크는 redis manager인데, 지금하고자 하는 것에는 사용하지 않는다.
다만, 1번 링크 설치 후에 간단한 key/value 값 넣고 확인해본다거나 하실려면 설치!

https://sourceforge.net/projects/redis-desktop-manager.mirror/

3. redis를 사용할 수 있는 것들 중 나는 cpp_redis를 선택했다.
아래 링크에서 체크아웃하였다. 우리는 visual studio를 통해 빌드할 예정이다.
https://github.com/Cylix/cpp_redis

4. 3번에서 체크 아웃 받은 프로젝트의 폴더로 가보면 아래 경로에 tacopie.sln 이 있다.
..\cpp_redis\msvc15

5. 만약 현재 환경이 visual studio 2017이고, Windows SDK 버전도 상위라면
프로젝트 속성에서 변경해줘야 한다.

6. 빌드를 완료하면, 아래 경로에 tacopie.lib 파일이 있을 것이다.
\cpp_redis\msvc15\x64\Debug 또는 Release

7. 이제 테스트를 위한 윈도우 콘솔 솔루션을 생성하고
TestRedisClient, TestRedisServer 와 같이 2개의 프로젝트를 생성한다.
프로젝트명은 각자 원하시는대로 하시면 된다.

8. 두 프로젝트 모두 다 tacopie.lib를 사용하기 위한 설정을 해준다.
나는 아래와 같이 4개의 항목을 수정했다.

디렉터리는 아래와 같이 2개를 추가 했다.
\cpp_redis\includes
\cpp_redis\includes\tacopie
 - 이 폴더 안에 tacopie.lib 파일을 넣어두었다.


 구성속성 > VC++ 디렉터리 > 포함 디렉터리
 구성속성 > VC++ 디렉터리 > 라이브러리 디렉터리
 구성속성 > C/C++ > 추가 포함 디렉터리
 구성속성 > 링커 > 입력 > 추가 종속성 (tacopie.lib 추가)


자.. 그러면 프로젝트 준비는 어느 정도 된 것 같고 아래에는 내가 테스트한 소스다.
github에 보면 example 코드가 있는데 그거와 거의 동일하다.
몇 가지 내가 주석을 달고, client 측에서 async_write를 사용한 것 빼고..

<TestRedisClient>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "pch.h"
#include <iostream>
#include <WinSock2.h>
#include <tacopie/tacopie>
#include <condition_variable>
#include <mutex>
#include <signal.h>
using namespace std;
std::condition_variable cv;
void signint_handler(int
{
    // 주의:
    // 스레드는 아래 두 메서드에 의해 깨어날 수도 있지만,
    // 타임 아웃으로 인해 깨어날 수도 있다.
    // 이 조건 변수를 기다리고 있는 스레드 중 한 개의 스레드를 깨운다.
    //cv.notify_one();
    // 이 조건 변수를 기다리고 있는 모든 스레드를 깨운다.
    cv.notify_all();
}
void on_new_message(tacopie::tcp_client& client, const tacopie::tcp_client::read_result& res) 
{
    if (res.success) 
    {
        std::cout << "Client recv data" << std::endl;
        client.async_write({ res.buffer, nullptr });
        client.async_read({ 1024std::bind(&on_new_message, std::ref(client), std::placeholders::_1) });
    }
    else 
    {
        std::cout << "Client disconnected" << std::endl;
        client.disconnect();
    }
}
int main()
{
    WORD version = MAKEWORD(22);
    WSADATA data;
    // 이 과정을 해주지 않으면 cpp_redis 정상적으로 동작하지 않는다.
    // 이 녀석도 소켓을 쓰는 거니까
    if (0 != WSAStartup(version, &data))
    {
        cout << "WSAStartup fail" << "\n";
        return -1;
    }
    tacopie::tcp_client client;
    client.connect("127.0.0.1"3000);
    client.async_read({ 1024std::bind(&on_new_message, std::ref(client), std::placeholders::_1) });
    vector<int> v = { 12345 };
    tacopie::tcp_client::write_request a;
    a.buffer.push_back(1);
    a.buffer.push_back(2);
    a.buffer.push_back(3);
    a.buffer.push_back(4);
    a.buffer.push_back(5);
    client.async_write({ a.buffer, nullptr });
    // SIGINT 값은 사용자가 Ctrl+C키를 입력했을 때 들어온다.
    // 즉, signint_handler함수를 호출해 notify 해줌으로써 
    // 아래에서 lock(mtx)에 잠긴 스레드를 깨운다.
    signal(SIGINT, &signint_handler);
    std::mutex mtx;
    std::unique_lock<std::mutex> lock(mtx);
    
    cv.wait(lock);
    
    WSACleanup();
    system("pause");
    return 0;
}
cs

<TestRedisServer>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "pch.h"
#include <tacopie/tacopie>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <signal.h>
#include <Winsock2.h>
std::condition_variable cv;
void signint_handler(int
{
    cv.notify_all();
}
void on_new_message(const std::shared_ptr<tacopie::tcp_client>& client, const tacopie::tcp_client::read_result& res) 
{
    if (res.success) 
    {
        std::cout << "Client recv data" << std::endl;
        client->async_write({ res.buffer, nullptr });
        client->async_read({ 1024std::bind(&on_new_message, client, std::placeholders::_1) });
    }
    else 
    {
        std::cout << "Client disconnected" << std::endl;
        client->disconnect();
    }
}
int main(void
{
    //! Windows netword DLL init
    WORD version = MAKEWORD(22);
    WSADATA data;
    if (WSAStartup(version, &data) != 0
    {
        std::cerr << "WSAStartup() failure" << std::endl;
        return -1;
    }
    tacopie::tcp_server s;
    s.start("127.0.0.1"3000, [](const std::shared_ptr<tacopie::tcp_client>& client) -> bool 
    {
        std::cout << "New client" << std::endl;
        client->async_read({ 1024std::bind(&on_new_message, client, std::placeholders::_1) });
        return true;
    });
    signal(SIGINT, &signint_handler);
    std::mutex mtx;
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock);
    WSACleanup();
    system("pause");
    return 0;
}
cs

2016년 5월 16일 월요일

vSphere Client 에서 가상 시스템 구성시..



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<keyword>esxi, vSphere Client, network
부딪혔던 문제들을 마구잡이로 기록하는 것이라.. 보기 불편하실 수 있습니다.
 
전달 목적보다는 저의 기억을 기록하는 것이 목적이기에..ㅠㅠ
 
It might be uncomfortable to read this posting. 
Because of this posting's purpose is just memo of the problems 
I have encountered.
 
esxi를 다른 컴퓨터에 설치하고 윈도우 머신이랑 연결하기 위해서 
 
윈도우 머신에는vSphere Client를 설치하였다. 

I have installed 'vSphere client' in window machine 
for connect to another computer (installed esxi).
 
centos 설치를 위해 가상시스템 잡고, 리소스 할당해서 돌렸는데.. 
 
인터넷이 되지 않는다-_-..방화벽에다 해당 IP도 등록했는데...
 
I install centos by virtual OS in esxi. 
But centos cannot connect ethernet. 
I already added IP to the firewall.
 
 
 
 
 
가상시스템이 아니라 메인 컴퓨터의 구성 > 네트워킹을 가면 

아래와 같은 그림을 볼 수 있다.

가상시스템을 만든 경우 (아래의 사진에서는 cent/my_test) 

VM 네트워크를 물리적 어댑터로연결해줘야한다.

You can see below picture in vSphere client window > main computer's 
component > networking. If you create virtual OS, 
then you have to connect 'VM network' -> physical adapter.
 
 
cs

A*, JPS 길찾기 알고리즘 시뮬레이션 사이트

https://qiao.github.io/PathFinding.js/visual/ 길 찾기 알고리즘 시행 과정을 보여주는 사이트다. 링크 메모..