Visual Studio Code, Python 개발환경 구축

1. Visual Studio Code vscode

MS가 배포하는 Electron Framwork 기반 Cross-Flatform Code editing

1.1. 설치

※ Developer Survey Results 2018 : https://insights.stackoverflow.com/survey/2018/

image
image

1.2. 특징

  • Fast, Powerful Editing
    • Linting, multi-cursor editing, parameter hints, and other powerful editing features.
    • Code Navigation and Refactoring
  • Meet IntelliSense.
    • syntax highlighting and autocomplete with IntelliSense, which provides smart completions based on variable types, function definitions, and imported modules.
  • Git commands built-in
  • Extensible and customizable
    • Install extensions to add new languages, themes, debuggers, and to connect to additional services

1.3. Getting Started, Top Extensions

1.4. 추천 Extensions

2. Python 개발환경

1.1. 설치

choco install python -y 
  • Linux : Centos 7
# 2.7.x 버전은 기본 설치 되어 있음 
# yum 패키지에서 3.4 버전밖에 없어 3.6 설치하려면 epel-release 저장소 추가 
sudo yum install -y epel-release

# python, pip 설치 
sudo yum install python36u python36u-pip

# python3, pip3 사용 하기위한 심볼릭 링크 
sudo ln -sf /usr/bin/python3.6 /usr/bin/python3 
sudo ln -sf /usr/bin/pip3.6 /usr/bin/pip3

1.2. PIP 패키지 관리

  • Python으로 작성된 패키지 소프트웨어를 설치/관리하는 패키지 관리 시스템
# flask 모듈 설치 
# 전역으로 설치하는것으로 linux의 경우 sudo권한이 필요하고 windows 10의 경우 Admin Role 필요 
## 권고 하지 않음 
pip install flask

# flask 모듈을 user 공간에 설치 (권고)
pip install flask --user 

# pip 설치된 모듈 보기 
pip freeze 

# pip 패키지 삭제 
pip uninstall flask

1.2.1 virtual 환경

  • 가상환경으로 Python 실행 및 패키지 관리
  • virtual 모듈 설치
    • virtualenv : 일반적으로 많이 사용되는 가상환경 관리 모듈
pip install virtualenv --user 

# linux 의 경우 yum으로도 설치 가능 (3.6 기준)
sudo yum install python36-virtualenv -y 
  • virtual 만들기
# python 3.6 환경의 virtual 환경 만들기 
virtualenv --python=/usr/bin/python3 venv

# 기본 virtual 환경 만들기
virtualenv venv

# Path 가 없어 명령어를 찾지 못할 경우 
python -m virtualenv venv
  • activate virtual
# linux 
source venv/bin/activate

# windows 
venv\Script\Activate
  • deactivate virtual
# linux 
deactivate

# windows
venv\Scripts\deactivate.bat

3. Python 개발환경 - vscode

  • Extensions 설치 : Python, Code Runner
  • Python 실행 - Context Menu (mouse right button)
    • Python : Run Python File in Terminal
      • 전체 파일 터미널 실행
      • virual 환경 지원 : 프로젝트 오픈시
        • vscode 폴더로 열면 해당 폴더를 기준으로 프로젝트로 인식
    • Code Runner : Context Menu의 Run Code (Ctrl+Alt+N)
      • 코드 셀렉션 부분 코드 실행 및 전체 파일 실행
      • virtual 환경 지원 안함

image

  • virtual 환경 선택 : 프로젝트 파일 오픈시 가능
    • Command palette 열기 (F1 or Ctrl+Shirt+p)
    • Python Select Interpreter → 선택

image

image

4. 기타 개발환경

choco install googlechrome -y
choco install 7zip -y
choco install conemu -y
choco install vscode -y
choco install python -y
choco install dotnetcore-sdk -y
choco install d2codingfont -y
choco install git -y
choco install tortoisegit -y
choco install curl -y

choco install fiddler -y
choco install filezilla -y
choco install dbeaver -y
  • ConEmu : cmd 대체 툴

    • ConEmu-Maximus5 is a Windows console emulator with tabs, which represents multiple consoles as one customizable GUI window with various features.
    • https://conemu.github.io/
      choco install conemu
  • MSYS2 : Git 설치 디렉토리에 위치

    • Add PATH : C:\Program Files\Git\usr\bin
      MSYS2 is a software distro and building platform for Windows
      At its core is an independent rewrite of MSYS, based on modern Cygwin 
      (POSIX compatibility layer) and MinGW-w64 with the aim of better interoperability with native Windows software. 
      It provides a bash shell, Autotools, revision control systems and the like for building native Windows applications using MinGW-w64 toolchains.
  • WSL : Windows Subsystem for Linux

'Dev' 카테고리의 다른 글

OS 커널 관련된 글들..  (0) 2008.09.01
요즘, 단상..  (0) 2006.03.28
Subversion 아직은...  (0) 2004.12.06
공익 광고 ..  (0) 2004.11.29
버전관리툴  (0) 2004.11.24

Gitlab Backup & Restore 방법

1. Backup 방법

sudo gitlab-rake gitlab:backup:create

백업을 하면 아래 경로에 백업 파일이 생성

  • /var/opt/gitlab/backups/
drwxr-----.  2 git  root      4096 2017-01-06 09:22 .
drwxr-xr-x. 13 root root      4096 2017-01-05 13:39 ..
-rw-------.  1 git  git  732047360 2017-01-06 09:20 1483662009_2017_01_06_gitlab_backup.tar

2. Restore 방법

먼저 2개의 서비스를 중지 시키고 상태를 확인

sudo gitlab-ctl stop unicorn
sudo gitlab-ctl stop sidekiq
# Verify
sudo gitlab-ctl status

백업된 파일을 기본 Backup 폴더로 위치

sudo cp 1393513186_2014_02_27_gitlab_backup.tar /var/opt/gitlab/backups/

Restore 명령

sudo gitlab-rake gitlab:backup:restore BACKUP=1393513186_2014_02_27

아래와 같은 에러 발생 (나의 경우)

rake aborted!
TypeError: no implicit conversion of nil into String

근본적인 방법은 아니지만, 백업 파일이 1개인 경우 백업 파일 이름없이 명령을 사용하면 해당 문제는 해결

sudo gitlab-rake gitlab:backup:restore 

위의 경우도 권한의 문제가 발생하니, 백업 파일의 666 이상의 권한과 디렉토리의 777 권한을 설정

기본적으로 git 계정으로 r 권한만 설정 되어 있음

sudo chmod 777 /var/opt/gitlab/backups/
sudo chmod 666 /var/opt/gitlab/backups/*

성공적으로 진행 되면 모든 데이터가 삭제 된다고 묻는 내용이 나오고 yes 키인하면 성공!!

3. 자동 백업

  • 서버측 스크립트(백업) : gitlab_backup.sh
#/bin/bash
sudo chmod 755 /var/opt/gitlab/backups/
sudo rm -rf /var/opt/gitlab/backups/*
sudo gitlab-rake gitlab:backup:create
sudo chmod 644 /var/opt/gitlab/backups/*
  • 클라이언트 백업 실행 및 복사 : gitlab_backup.bat
    계정의 ssh 의 공개키기반 자동 로그인 및 sudoers 에 NOPASSWD 옵션 추가
ssh -t [서버] script/gitlab_backup.sh
scp [서버]:/var/opt/gitlab/backups/* .


'Dev > Linux' 카테고리의 다른 글

ubuntu server 12.04  (0) 2013.10.28

1. 기본 설정 

# JAVA 설치 
- OS에 맞춰 설치(다운로드) 후 JAVA_HOME 환경변수 설정 


# Hadoop 실행 계정 생성 및 SSH Key 등록 

- 노드에서 다른 노드로 접속(ssh) 시 패스워드 없이 접속을 위해 키 생성 및 등록 

- ssh localhost 명령에서 패스워드가 없이 접속이 되어야 성공 

$ useradd hadoop


$ su - hadoop

$ ssh-keygen -t rsa

$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

$ chmod 0600 ~/.ssh/authorized_keys


$ ssh localhost   # 패스워드 없이 접속이 되어야 함 


# Hadoop Download 

http://hadoop.apache.org/releases.html

wget http://mirror.apache-kr.org/hadoop/common/hadoop-2.7.2/hadoop-2.7.2.tar.gz

tar -zxvf hadoop-2.7.2.tar.gz

sudo cp -R hadoop-2.7.2 /usr/local/

sudo chown -R hadoop:hadoop /usr/local/hadoop-2.7.2

sudo ln -s /usr/local/hadoop-2.7.2 /usr/local/hadoop

# ~/.bashrc 

# HADOOP_HOME  설정 및 bin path 설정 


export HADOOP_HOME=/usr/local/hadoop

export PATH=$PATH:$HADOOP_HOME/bin


2. Hadoop 설정파일 

# $HADOOP_HOME/etc/hadoop/hadoop-env.sh

- JAVA_HOME 설정 

# The java implementation to use.

export JAVA_HOME=/usr/local/java


# $HADOOP_HOME/etc/hadoop/core-site.xml

- 9000 포트에 hdfs:// 프로토콜 서비스 

- hadoop.tmp.dir 의 디폴트 경로 :  /tmp/hadoop-${user.name} 

<configuration>

    <property>

        <name>fs.defaultFS</name>

        <value>hdfs://0.0.0.0:9000</value>

    </property>

</configuration>

- 추가적으로 hadoop.tmp.dir 설정이 필요 하다면

<configuration>

    <property>

        <name>fs.defaultFS</name>

        <value>hdfs://0.0.0.0:9000</value>

    </property>

    <property>

       <name>hadoop.tmp.dir</name>

       <value>/hdfs/dfs/tmp</value>

    </property>

</configuration>


# $HADOOP_HOME/etc/hadoop/hdfs-site.xml

- dfs.replication : block replication (default : 3)

- dfs.namenode.name.dir : namenode 디렉토리 위치 

- dfs.datanode.data.dir : datanode 디렉토리 위치 

- dir을 지정하지 않으면 각각 file://${hadoop.tmp.dir}/dfs/name file://${hadoop.tmp.dir}/dfs/data 에 위치 

<configuration>

    <property>

        <name>dfs.replication</name>

        <value>1</value>

    </property>

    <property>

        <name>dfs.namenode.name.dir</name>

        <value>file:/hdfs/dfs/name</value>

    </property>

    <property>

        <name>dfs.datanode.data.dir</name>

        <value>file:/hdfs/dfs/data</value>

    </property>

</configuration>


# namenode format 

# dir 경로에 권한 부여 

$ sudo mkdir /hdfs

$ sudo chown hadoop:hadoop /hdfs


# namenode fomat 

$ hdfs namenode -format 



# $HADOOP_HOME/etc/hadoop/mapred-site.xml

$ cp $HADOOP_HOME/etc/hadoop/mapred-site.xml.template $HADOOP_HOME/etc/hadoop/mapred-site.xml

<configuration>

    <property>

        <name>mapreduce.framework.name</name>

        <value>yarn</value>

    </property>

</configuration>


# $HADOOP_HOME/etc/hadoop/yarn-site.xml

<configuration>

    <property>

        <name>yarn.nodemanager.aux-services</name>

        <value>mapreduce_shuffle</value>

    </property>

</configuration>


3. Hadoop 구동

- hdfs 및 yarn 서비스 시작  (hadoop 계정으로 실행)

- jps 를 통해서 Namemode, Datanode 등 실행 되는지 학인 

$ sudo - hadoop 

$ $HADOOP_HOME/sbin/start-dfs.sh

$ $HADOOP_HOME/sbin/start-yarn.sh 


# 서비스 확인 

$ jps

2609 DataNode

2485 NameNode

3334 Jps

2779 SecondaryNameNode

2940 ResourceManager

3039 NodeManager


$ hdfs dfs -ls /

$ hdfs dfs -mkdir /data

$ hdfs dfs -put /home/hadoop/data/* /data/


# 서비스 PORT

- 9000 : ipc 서비스 포트, hdfs:// 

- 50070 : Namenode 웹 어드민 

- 50075 : Datanode 웹 어드민 


'Dev > Data' 카테고리의 다른 글

Spark 테스트 (Windows, Scala, Self-Contained Applications)  (1) 2015.11.18
Apache Tajo 테스트 (Windows)  (0) 2015.11.13
Apache Hadoop 2.7.1 (Windows)  (0) 2015.11.13
Spark 테스트 (Windows, Python 환경)  (0) 2015.11.11
Spark 설치 (Standalone)  (1) 2015.11.11

# VisualVM

- JAVA의 VM을 모니터링 할 수 있는 GUI 툴  

- JDK 1.7 이상의 경우 JAVA_HOME/bin 밑에 포함 되어 있음 (e.g. windows - jvisualvm.exe)

- 별도로 다운 받을 경우 : https://visualvm.java.net/


# 원격접속 준비 (서버)

- 원격으로 접속을 할 경우 host 서버측에 rmiregistry 및 jstatd 데몬 실행을 실행 시켜 놓아야 함

- jstatd 데몬 실행을 위한 policy 파일 작성 (tools.policy)

grant codebase "file:${java.home}/../lib/tools.jar" {

   permission java.security.AllPermission;

};


- rmiregistry 실행 및 jstatd 실행 

# rmiregistry 2020 &

# jstatd -p 2020 -J-Djava.security.policy=tools.policy &


** centos 의 경우 방화벽을 열어야 하는데 2020 포트 이외에 랜덤한 포트를 하나 더 연결 하므로 해당 포트를 찾아서 열던가, 방화벽을 끄도록 함.

tcp        0      0 :::2020                     :::*                        LISTEN

tcp        0      0 ::ffff:127.0.0.1:8005       :::*                        LISTEN

tcp        0      0 :::8009                     :::*                        LISTEN

tcp        0      0 :::46092                    :::*                        LISTEN   <- ** 이 포트 (랜덤 포트)


- 별도 랜덤한 포트를 연결 할때 hostname으 IP를 찾아서 연결을 시도함

만약 hostname 의 문제로 연결이 안되는 경우 클라이언트에 hosts 파일에 name 등록 후 서버 측 jstatd 에 연결할 hostname 을 명시해 줌  

# jstatd -p 2020 -J-Djava.security.policy=tools.policy -Djava.rmi.server.hostname=centos &


# VisualVM 실행 

- Remote 항목에 서버를 등록

- 해당 서버 항목의 오른쪽 버튼의 Add jstatd Connection 으로 연결 설정을 열어 포트를 2020 으로 수정 


# Visual GC 추가 

-  Tools -> Plugins 메뉴에서 Visual GC Install 후 재 시작 하면 아래와 같은 화면이 표시됨 


# JVM GC 로그 남기기 

- JVM 자체적으로 GC의 Collection 로그를 남기긱 위해서, JAVA 실행 시 옵션 추가 

- 서버에 많은 부하를 주는 내용이 아니라, 별도의 GC 모니터링이 필요 하다면 추가 

-verbose:gc -XX:+PrintGCTimeStamps -Xloggc:/usr/local/tomcat/logs/gc.log"


- 전체 실행 시간 누적 시간(초), Young GC 및 Old GC (Full GC)의 실행 정보, 수행 시간 등이 기록  

# tail gc.log

2.207: [GC pause (G1 Evacuation Pause) (young) 25M->6191K(512M), 0.0208509 secs]

3.074: [GC pause (G1 Evacuation Pause) (young) 27M->10M(512M), 0.0215781 secs]

3.335: [GC pause (G1 Evacuation Pause) (young) 31M->12M(512M), 0.0163386 secs]

17.901: [GC pause (G1 Evacuation Pause) (young) 43M->19M(512M), 0.0165513 secs]

40.583: [GC pause (G1 Evacuation Pause) (young) 158M->37M(512M), 0.3734718 secs]

42.101: [GC pause (G1 Evacuation Pause) (young) 44M->35M(512M), 0.1114258 secs]

161.958: [GC pause (G1 Evacuation Pause) (young) 68M->37M(512M), 0.1038507 secs]

172.492: [GC pause (G1 Evacuation Pause) (young) 90M->43M(512M), 0.1775954 secs]

178.975: [GC pause (G1 Evacuation Pause) (young) 72M->44M(512M), 0.1478728 secs]

191.487: [GC pause (G1 Evacuation Pause) (young) 105M->49M(512M), 0.1640510 secs]


# 참고 

- JAVA GC : http://d2.naver.com/helloworld/1329

- GC 튜닝 : http://d2.naver.com/helloworld/37111

- G1 GC 설명 : http://logonjava.blogspot.kr/2015/08/java-g1-gc-full-gc.html


'Dev > Java' 카테고리의 다른 글

Mybatis 테스트  (1) 2014.10.30

# Scala 를 이용한 Spark Self-Contained Applications 테스트 


# 설치 

- Scala 다운로드 : http://www.scala-lang.org/download/all.html (2.10.6 버전)

- SBT(Scala Build Tool) 다운로드 : http://www.scala-sbt.org/download.html

- 두개의 프로그램 모두 공백이 없는 경로에 설치 하거나 mklink를 이용하여 공백이 없는 경로에 접근 가능하게 작업

- 각각의 "scala\bin" "sbt\bin" 디렉토리를 PATH 설정 


# 빌드 준비 

- 아래와 같은 Spark 빌드 환경 설정을 위해 .sbt 파일을 작성

- Scala 버전 2.10.6, Spark 버전 1.5.2 

name := "App"
version := "1.0"
scalaVersion := "2.10.6"

libraryDependencies += "org.apache.spark" %% "spark-core" % "1.5.2"

- sbt run 을 실행하여 빌드 및 실행 (처음에는 의존성 파일 설정을 위해 오래 걸림


- sublime text 3 사용시 Scala 빌드 설정 파일

- scala.sublime-build

{

    "cmd": ["sbt_bin_path\\sbt.bat", "run"],

    "working_dir": "${project_path:${folder}}",

    "selector": "source.scala"

}




# Scala 코드

http://cdecl.tistory.com/306 의  spark_movelens.py 와 같은 기능을 하는 Scala 코드

- Scala의 Self-Contained Applications 환경에서는 sc.stop() 을 하지 않으면 "ERROR Utils: uncaught error in thread SparkListenerBus, stopping SparkContext" 이란 에러 발생함 

import org.apache.spark.SparkContext
import org.apache.spark.SparkContext._

import org.apache.log4j.Logger
import org.apache.log4j.Level


object App {
	def main(args: Array[String]) {
		Logger.getLogger("org").setLevel(Level.WARN)
		Logger.getLogger("akka").setLevel(Level.WARN)

		val sc = new SparkContext("local[*]", "MyApp")
		RDDRun(sc)
		sc.stop()
	}


	def RDDRun(sc: SparkContext) {
		val ratings = "D:/hadoop/data/ml-20m/ratings.csv"
		
		val rddMovie = (sc: SparkContext) => {
			val movies =  "D:/hadoop/data/ml-20m/movies.csv"
			val rdd = sc.textFile(movies)
			val header = rdd.first()

			rdd.filter(_ != header).map(_.split(",")).map(x => (x(0), x(1)))
		}

		val rdd = sc.textFile(ratings)
		val header = rdd.first()

		val rddR = rdd.filter(_ != header).map(_.split(",")).map(x => (x(1), x(2).toFloat))
			.groupByKey().mapValues(x=> x.sum / x.size)
			.join(rddMovie(sc)).sortBy(_._2._1)
			.map(x=> (x._1, x._2._1, x._2._2))		

		for (t <- rddR.collect()) {
			println("%s, %f, %s".format(t._1, t._2, t._3))
		}

	}
}


# 비교

- Python 코드 : [Finished in 175.3s] http://cdecl.tistory.com/306 

- Scala 코드 : [Finished in 70.5s]

- Scala 쪽이 월등하게 빠르므로, 프로토타입 같은 작업시 Python이 간단해 보이지만 Staging 서비스의 경우 Scala로 작성하는 것이 성능상 이점이 있음


'Dev > Data' 카테고리의 다른 글

Hadoop Single Node 설치 (linux)  (0) 2016.07.23
Apache Tajo 테스트 (Windows)  (0) 2015.11.13
Apache Hadoop 2.7.1 (Windows)  (0) 2015.11.13
Spark 테스트 (Windows, Python 환경)  (0) 2015.11.11
Spark 설치 (Standalone)  (1) 2015.11.11


# Apache Tajo 

- Apache Tajo™: A big data warehouse system on Hadoop

http://tajo.apache.org/


# Apache Tajo 설치 

- Download : http://tajo.apache.org/downloads.html

- 최신 바이너리(Latest Release 0.11.0) 를 받아서 압축을 풀기 


- conf/tajo-env.cmd 파일의 HADOOP_HOME 과 JAVA_HOME 세팅 

@rem Hadoop home. Required

set HADOOP_HOME=%HADOOP_HOME%


@rem The java implementation to use.  Required.

set JAVA_HOME=%JAVA_HOME%


# Apache Tajo 실행

bin\start-tajo.cmd


# tsql 실행 및 테스트 

- 영화의 평점 샘플 데이터 활용 - http://grouplens.org/datasets/movielens/

- http://files.grouplens.org/datasets/movielens/ml-20m.zip  (MovieLens 20M Dataset 사용)


> hadoop fs -ls /user/cdecl/data                                                                     

Found 6 items                                                                                        

-rw-r--r--   1 cdecl supergroup       8652 2015-11-13 13:03 /user/cdecl/data/README.txt              

-rw-r--r--   1 cdecl supergroup     569517 2015-11-13 13:03 /user/cdecl/data/links.csv               

-rw-r--r--   1 cdecl supergroup    1397542 2015-11-13 13:03 /user/cdecl/data/movies.csv              

-rw-r--r--   1 cdecl supergroup        258 2015-11-13 13:03 /user/cdecl/data/movies.csv.dsn          

-rw-r--r--   1 cdecl supergroup  533444411 2015-11-13 13:03 /user/cdecl/data/ratings.csv             

-rw-r--r--   1 cdecl supergroup   16603996 2015-11-13 13:03 /user/cdecl/data/tags.csv              


- ratings.csv 

- 영화 평점 정보, 약 500MB, 20,000,264 rows

Ratings Data File Structure (ratings.csv)

-----------------------------------------

All ratings are contained in the file `ratings.csv`.

    userId,movieId,rating,timestamp


userId,movieId,rating,timestamp

138493,60816,4.5,1259865163

138493,61160,4.0,1258390537

138493,65682,4.5,1255816373

138493,66762,4.5,1255805408

138493,68319,4.5,1260209720


- movies.csv

- 영화 정보, 약 1MB , 27,279 rows

Movies Data File Structure (movies.csv)

---------------------------------------

Movie information is contained in the file `movies.csv`. Each line of this file after the header row represents one movie, and has the following format:

    movieId,title,genres


movieId,title,genres

131241,Ants in the Pants (2000),Comedy|Romance

131243,Werner - Gekotzt wird später (2003),Animation|Comedy

131248,Brother Bear 2 (2006),Adventure|Animation|Children|Comedy|Fantasy

131250,No More School (2000),Comedy

131252,Forklift Driver Klaus: The First Day on the Job (2001),Comedy|Horror



- tsql 실행 

D:\hadoop\tajo-0.11.0

> bin\tsql

starting cli, logging to D:\hadoop\tajo-0.11.0\logs\tajo.log


Try \? for help.

default>


CREATE EXTERNAL table movies ( mid int,  title text,  genres text )

USING TEXT WITH ('text.delimiter'=',', 'text.skip.headerlines'='1')

LOCATION 'hdfs://localhost:9000/user/cdecl/data/movies.csv';


create EXTERNAL table ratings ( userid int, mid int, rate int, timest text )

USING TEXT WITH ('text.delimiter'=',', 'text.skip.headerlines'='1')

LOCATION 'hdfs://localhost:9000/user/cdecl/data/ratings.csv';


SELECT a.mid, max(b.title), avg(a.rate) 

FROM ratings a join movies b on a.mid = b.mid 

GROUP BY a.mid 

ORDER BY avg(a.rate) DESC 

LIMIT 10;



- 같은 결과를 얻기위해 Spark(Python)의 경우 약 3분의 소요된 반면 Tajo의 경우 약 1분 정도로 단순 Single node에서 실행은 빠른것으로 판단

- 허나 Spark 나 Tajo 의 경우 1개의 노드가 아닌 많은 Cluster에 의해 운영되어 성능을 극대화에 목적이 있으므로 로컬에서는 단순 테스트로만..

- Spark(Python) Test : http://cdecl.tistory.com/306




** Apache Hadoop을 Windows 10에 설치 및 테스트 


Apache Hadoop for Windows 

- 깃헙에서 소스를 받아 빌드 작업을 해야 하지만, 친철하게 Windows용 64비트 비공식 빌드가 있어 해당 바이너리를 다운로드 

- karthikj1/Hadoop-2.7.1-Windows-64-binaries https://github.com/karthikj1/Hadoop-2.7.1-Windows-64-binaries

- Single Node Cluster, Pseudo-Distributed Mode 로 설치 


# 설치

- 다운로드 받은 파일을 공백이 없는 위치에 압축 풀기

- HADOOP_HOME , JAVA_HOME 환경번수 세팅 

- PATH에 HADOOP_HOME\bin 경로 추가 

* 시스템-고급 시스템 설정-환경변수 세팅 

HADOOP_HOME=D:\hadoop\hadoop-2.7.1

JAVA_HOME=D:\hadoop\Java


PATH=%PATH%;D:\hadoop\hadoop-2.7.1\bin


* Java를 기본 설치 할 경우 공백을 들어간 "C:\Program Files\Java\jre1.8.0_66"에 설치가 되는데 mklink를 이용하여 공백없는 경로에 심볼릭 링크 생성 

mklink /j d:\hadoop\Java "C:\Program Files\Java\jre1.8.0_66"

d:\hadoop\Java <<===>> C:\Program Files\Java\jre1.8.0_66에 대한 교차점을 만들었습니다.


# Hadoop Conifg 설정 

- %HADOOP_HOME%\etc\hadoop\core-site.xml

- Hadoop 인터페이스 서비스 URI 설정 

- 외부로 서비스 노출 하고  싶다면 hdfs://0.0.0.0:9000 으로 세팅

<configuration>
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://localhost:9000</value>
    </property>
</configuration>

fs.defaultFS:

The name of the default file system. A URI whose scheme and authority determine the FileSystem implementation. The uri's scheme determines the config property (fs.SCHEME.impl) naming the FileSystem implementation class. The uri's authority is used to determine the host, port, etc. for a filesystem.


- %HADOOP_HOME%\etc\hadoop\hdfs-site.xml

- dfs.replication 블록 복제, 파일 복제 개수를 지정 

- namenode 와 datanode 의 경로를 지정 (옵션), 지정하지 않으면 /tmp 밑에 생성함

- file:/ 이 경로는 현재 드라이브 루트를 의미 (c:\ or d:\)

<configuration>
	<property>
		<name>dfs.replication</name>
		<value>1</value>
	</property>
	<property>
		<name>dfs.namenode.name.dir</name>
		<value>file:/hadoop/data/dfs/namenode</value>
	</property>
	<property>
		<name>dfs.datanode.data.dir</name>
		<value>file:/hadoop/data/dfs/datanode</value>
	</property>
</configuration>

dfs.replication:

Default block replication. The actual number of replications can be specified when the file is created. The default is used if replication is not specified in create time.


dfs.namenode.name.dir:

Determines where on the local filesystem the DFS name node should store the name table(fsimage). If this is a comma-delimited list of directories then the name table is replicated in all of the directories, for redundancy.


dfs.datanode.data.dir:

Determines where on the local filesystem an DFS data node should store its blocks. If this is a comma-delimited list of directories, then data will be stored in all named directories, typically on different devices. Directories that do not exist are ignored.


- %HADOOP_HOME%\etc\hadoop\yarn-site.xml

- yarn 설정 및 hadoop 어플리케이션 classpath 설정 

<configuration>
    <property>
       <name>yarn.nodemanager.aux-services</name>
       <value>mapreduce_shuffle</value>
    </property>
    <property>
       <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
       <value>org.apache.hadoop.mapred.ShuffleHandler</value>
    </property>
    <property>
       <name>yarn.application.classpath</name>
       <value>
            %HADOOP_HOME%\etc\hadoop,
            %HADOOP_HOME%\share\hadoop\common\*,
            %HADOOP_HOME%\share\hadoop\common\lib\*,
            %HADOOP_HOME%\share\hadoop\mapreduce\*,
            %HADOOP_HOME%\share\hadoop\mapreduce\lib\*,
            %HADOOP_HOME%\share\hadoop\hdfs\*,
            %HADOOP_HOME%\share\hadoop\hdfs\lib\*,         
            %HADOOP_HOME%\share\hadoop\yarn\*,
            %HADOOP_HOME%\share\hadoop\yarn\lib\*
       </value>
    </property>
</configuration>

yarn.nodemanager.aux-services:

The auxiliary service name. Default value is omapreduce_shuffle


yarn.nodemanager.aux-services.mapreduce.shuffle.class:

The auxiliary service class to use. Default value is org.apache.hadoop.mapred.ShuffleHandler


yarn.application.classpath:

CLASSPATH for YARN applications. A comma-separated list of CLASSPATH entries.


- %HADOOP_HOME%\etc\hadoop\mapred-site.xml

- 맵리듀스 런타임 프레임웍 설정 

<configuration>
    <property>
       <name>mapreduce.framework.name</name>
       <value>yarn</value>
    </property>
</configuration>

mapreduce.framework.name:

The runtime framework for executing MapReduce jobs. Can be one of local, classic or yarn.


# Namenode 포맷

%HADOOP_HOME%\bin\hdfs namenode -format 


# HDFS (Namenode and Datanode), YARN (Resource Manager and Node Manager) 실행 

%HADOOP_HOME%sbin\start-dfs.cmd

%HADOOP_HOME%sbin\start-yarn.cmd


* 콘솔창이 4개가 실행되면서 각각의 서비스 시작 


# 서비스 확인 

- http://localhost:8042Resource Manager and Node Manager : 

http://localhost:50070Namenode 


* http://localhost:9000 - Service URI


# 테스트 (Apache Spark, Python)

> hadoop fs -mkdir -p /user/cdecl/data 


> hadoop fs -ls /                                                                                    

Found 1 items                                                                                        

drwxr-xr-x   - cdecl supergroup          0 2015-11-13 13:02 /user

                                    

> hadoop fs -put D:\hadoop\data\ml-20m\* /user/cdecl/data


> hadoop fs -ls /user/cdecl/data                                                                     

Found 6 items                                                                                        

-rw-r--r--   1 cdecl supergroup       8652 2015-11-13 13:03 /user/cdecl/data/README.txt              

-rw-r--r--   1 cdecl supergroup     569517 2015-11-13 13:03 /user/cdecl/data/links.csv               

-rw-r--r--   1 cdecl supergroup    1397542 2015-11-13 13:03 /user/cdecl/data/movies.csv              

-rw-r--r--   1 cdecl supergroup        258 2015-11-13 13:03 /user/cdecl/data/movies.csv.dsn          

-rw-r--r--   1 cdecl supergroup  533444411 2015-11-13 13:03 /user/cdecl/data/ratings.csv             

-rw-r--r--   1 cdecl supergroup   16603996 2015-11-13 13:03 /user/cdecl/data/tags.csv                

 


# SparkApp
from pyspark import SparkContext


def main():
	sc = SparkContext("local[*]", "SparkApp")

	ratings = "hdfs://localhost:9000/user/cdecl/data/movies.csv"
	rdd = sc.textFile(ratings)

	print(rdd.take(5))	


if __name__ == "__main__":
	main()


['movieId,title,genres', '1,Toy Story (1995),Adventure|Animation|Children|Comedy|Fantasy', '2,Jumanji (1995),Adventure|Children|Fantasy', '3,Grumpier Old Men (1995),Comedy|Romance', '4,Waiting to Exhale (1995),Comedy|Drama|Romance']


참고 : 

http://hadoop.apache.org/docs/r2.7.1/hadoop-project-dist/hadoop-common/SingleCluster.html

http://www.srccodes.com/p/article/38/build-install-configure-run-apache-hadoop-2.2.0-microsoft-windows-os



# Spark 어플리케이션 실행 방법

- Spark 어플리케이션을 실행 하기 위해서 3가지 방법을 제공

http://spark.apache.org/docs/latest/quick-start.html

 


1. Spark Shell 을 이용한 인터랙티브한 환경에서 실행 (scala : bin/spark-shell, python: bin/pyspark)

>> bin\pyspark Python 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015, 02:16:59) [MSC v.1900 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. 15/11/11 20:05:54 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 15/11/11 20:05:57 WARN MetricsSystem: Using default name DAGScheduler for source because spark.app.id is not set. Welcome to ____ __ / __/__ ___ _____/ /__ _\ \/ _ \/ _ `/ __/ '_/ /__ / .__/\_,_/_/ /_/\_\ version 1.5.1 /_/ Using Python version 3.5.0 (v3.5.0:374f501f4567, Sep 13 2015 02:16:59) SparkContext available as sc, HiveContext available as sqlContext. >>> rdd = sc.textFile('README.md') >>> rdd.count() 98




2. spark-submit 툴을 이용하여 소스나 패키지를 제출하여 실행

## # test.py from pyspark import SparkContext sc = SparkContext("local", "Simple App") rdd = sc.textFile('README.md') print(rdd.count())


%SPARK_HOME%\bin\spark-submit test.py

98



3. 단독 어플리케이션으로 실행 

PYTHONPATH를 설정하여 패키지 참조 하여야 사용 가능 

PYTHONPATH=%SPARK_HOME%/python/lib/pyspark.zip;%SPARK_HOME%/python/lib/py4j-0.8.2.1-src.zip

python test.py

98





# Spark 예제

영화의 평점 샘플 데이터 활용 - http://grouplens.org/datasets/movielens/

http://files.grouplens.org/datasets/movielens/ml-20m.zip  (MovieLens 20M Dataset 사용)

- 사용자에 의해 점수가 매겨진 파일(ratings.csv)을 영화별 평점을 구하여 정렬. 영화정보(movies.csv영화명)과 함께 조인하여 보여 주는 예제


- ratings.csv 

- 영화 평점 정보, 약 500MB, 20,000,264 rows

Ratings Data File Structure (ratings.csv)

-----------------------------------------

All ratings are contained in the file `ratings.csv`.

    userId,movieId,rating,timestamp


userId,movieId,rating,timestamp

138493,60816,4.5,1259865163

138493,61160,4.0,1258390537

138493,65682,4.5,1255816373

138493,66762,4.5,1255805408

138493,68319,4.5,1260209720


- movies.csv

- 영화 정보, 약 1MB , 27,279 rows

Movies Data File Structure (movies.csv)

---------------------------------------

Movie information is contained in the file `movies.csv`. Each line of this file after the header row represents one movie, and has the following format:

    movieId,title,genres


movieId,title,genres

131241,Ants in the Pants (2000),Comedy|Romance

131243,Werner - Gekotzt wird später (2003),Animation|Comedy

131248,Brother Bear 2 (2006),Adventure|Animation|Children|Comedy|Fantasy

131250,No More School (2000),Comedy

131252,Forklift Driver Klaus: The First Day on the Job (2001),Comedy|Horror


# spark_movelens.py

from pyspark import SparkContext from statistics import mean if __name__ == "__main__": sc = SparkContext("local[*]", "Simple App") ratings = "D:/hadoop/data/ml-20m/ratings.csv" movies = "D:/hadoop/data/ml-20m/movies.csv" movie = sc.textFile(movies) header = movie.first() dic = movie.filter(lambda x: x != header).map(lambda x: x.split(',')).map(lambda x: (x[0],x[1])) data = sc.textFile(ratings) header = data.first() rdd = data.filter(lambda x: x != header).map(lambda x: x.split(','))\ .map(lambda x: (x[1], float(x[2]))).groupByKey().mapValues(list)\ .map(lambda x: (x[0], round(mean(x[1]), 2)))\ .join(dic).sortBy(lambda x: x[1][0])\ .map(lambda x: (x[0], x[1][0], x[1][1])) for id, avg, title in rdd.collect(): print('{} {} - {}'.format(id, avg, title.encode('utf8')))

  

- 위의 내용을 Spark SQL로 구현 


# spark_sql.py

from pyspark.sql import SQLContext, Row from pyspark import SparkContext if __name__ == "__main__": sc = SparkContext("local[*]", "Simple SQL App") sqlContext = SQLContext(sc) ratings = "D:/hadoop/data/ml-20m/ratings.csv" moviepath = "D:/hadoop/data/ml-20m/movies.csv" movie = sc.textFile(moviepath) header = movie.first() rdd = movie.filter(lambda x: x != header).map(lambda x: x.split(','))\ .map(lambda x: Row(id=x[0], title=x[1])) data = sc.textFile(ratings) header = data.first() rddRating = data.filter(lambda x: x != header).map(lambda x: x.split(','))\ .map(lambda x: Row(id=x[1], rating=float(x[2]))) sqlContext.createDataFrame(rdd).registerTempTable('movies') sqlContext.createDataFrame(rddRating).registerTempTable('ratings') tbl = sqlContext.sql(""" SELECT a.id, b.title, avg(a.rating) as rating FROM ratings a join movies b WHERE a.id = b.id GROUP BY a.id, b.title ORDER BY avg(a.rating) """) tblMap = tbl.map(lambda x: (x.id, x.title, x.rating)) for a, b, c in tblMap.collect(): print("{}({}): {}".format(a, round(c, 2), b.encode('utf8')))



'Dev > Data' 카테고리의 다른 글

Hadoop Single Node 설치 (linux)  (0) 2016.07.23
Spark 테스트 (Windows, Scala, Self-Contained Applications)  (1) 2015.11.18
Apache Tajo 테스트 (Windows)  (0) 2015.11.13
Apache Hadoop 2.7.1 (Windows)  (0) 2015.11.13
Spark 설치 (Standalone)  (1) 2015.11.11


# Apache Spark 

- http://spark.apache.org/

- Apache Spark™ is a fast and general engine for large-scale data processing.


Spark 의 핵심은 무엇인가? RDD! : http://www.slideshare.net/yongho/rdd-paper-review

- Spark programming guide (번역) : http://www.raonbit.com/spark-programming-guide/



# Spark 설치 (Standalone, Python 기준)


- Java 설치 (1.8)

# Ubuntu 

sudo apt-get install python-software-properties

sudo add-apt-repository ppa:webupd8team/java

sudo apt-get update

sudo apt-get install oracle-java8-installer


# Windows 

http://www.java.com/ko/download/


- Apache Spark 다운로드

http://spark.apache.org/downloads.html (Spark 1.5.2 Pre-built for Hadoop 2.6 and later)


# Ubuntu 

wget http://apache.mirror.cdnetworks.com/spark/spark-1.5.2/spark-1.5.2-bin-hadoop2.6.tgz

tar -zxvf spark-1.5.2/spark-1.5.2-bin-hadoop2.6.tgz

sudo mv spark-1.5.2-bin-hadoop2.6 /usr/local/

sudo ln -s /usr/local/spark-1.5.2-bin-hadoop2.6 /usr/local/spark


- Python 설치 (3.5 기준, 버전은 개인 취향?)  

https://www.python.org/


Ubuntu 15.10 의 경우 3.4 버전까지 기본 설치 되어 있음


- Hadoop 다운로드

Hadoop을 저장소로 사용하지 않으면 설치는 옵션이나 Windows의 경우 최소 winutils.exe 이 필요 하므로 그냥 Windows용 Hadoop 설치

압축을 풀고 HADOOP_HOME 환경 변수만 잡아주면 됨

# Hadoop for Windows 


비공식 바이너리 : https://github.com/karthikj1/Hadoop-2.7.1-Windows-64-binaries/releases 





# Spark 설정


- Path 설정

PYTHONPATH는 단독 어플리케이션 작성 시 spark 패키지를 참조하기 위한 세팅 

Ubuntu 예제 (.profile)


export JAVA_HOME=/usr/lib/jvm/java-8-oracle

export SPARK_HOME=/usr/local/spark

export PYTHONPATH=$SPARK_HOME/python/lib/pyspark.zip:$SPARK_HOME/python/lib/py4j-0.8.2.1-src.zip

export HADOOP_HOME=/usr/local/hadoop   # 옵션

Windows 환경변수 세팅 (공백이 없는 경로로 하며, 필요시 mklink를 이용하여 심볼릭 링크 설정을 하면 편함)


%JAVA_HOME%

%SPARK_HOME%

%PYTHONPATH%  

%HADOOP_HOME%



* Windows의 경우 %HADOOP_HOME% 세팅을 하지 않는 경우 아래와 같은 에러가 발생 


ERROR Shell: Failed to locate the winutils binary in the hadoop binary path

java.io.IOException: Could not locate executable null\bin\winutils.exe in the Hadoop binaries.


* Windows 에서 hive 에러 날 경우 

%HADOOP_HOME%/bin/winutils.exe chmod 777 D:\tmp\hive


- conf 설정 

cp $SPARK_HOME/conf/log4j.properties.template log4j.properties


# log4j.properties 파일편집

log4j.rootCategory=WARN, console  # INFO->WARN, INFO정보가 많이 출력 되므로 수정   




# Spark 테스트 (Shell)




cdecl@ubuntu:/usr/local/spark$ bin/pyspark Python 2.7.10 (default, Oct 14 2015, 16:09:02)

[GCC 5.2.1 20151010] on linux2
Type "help", "copyright", "credits" or "license" for more information.
15/11/11 18:53:30 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
15/11/11 18:53:30 WARN Utils: Your hostname, ubuntu resolves to a loopback address: 127.0.1.1; using 192.168.137.143 instead (on interface eth0)

15/11/11 18:53:30 WARN Utils: Set SPARK_LOCAL_IP if you need to bind to another address

15/11/11 18:53:35 WARN MetricsSystem: Using default name DAGScheduler for source because spark.app.id is not set.
Welcome to
____ __


/ __/__ ___ _____/ /__
_\ \/ _ \/ _ `/ __/ '_/
/__ / .__/\_,_/_/ /_/\_\ version 1.5.2
/_/
Using Python version 2.7.10 (default, Oct 14 2015 16:09:02)
SparkContext available as sc, HiveContext available as sqlContext.
>>> rdd = sc.textFile('README.md')
>>> rdd.count()
98
>>>





# TCmalloc (Thread-Caching memory allocation)

https://code.google.com/p/gperftools/

- 구글이 만든 성능 도구에 포함되어 있는 힙 메모리 할당자로서 크롬 및 많은 프로젝트에 사용 

- 기존의 malloc 으로 대표되는 할당자의 경우 멀티쓰레드의 최적화가 고려되지 않은 상황의 구현체이기 때문에, Thread가 난무하는 현실 세계에서는 많은 성능 저하가 있다고 함 (메모리 할당, 관리도 동시성을 고려해야 하므로..)

- 이쪽 계열 라이브러리 중에서는 가장 많이 알려져 있고, 기본 할당기에 비해 비약적인 성능 향상이 있다고 함.

- 그리고 적용 방법도 드라마틱 하게, 인상적임. 



# 리눅스(Ubuntu, 14.10) 환경에서의 TCmalloc 

- 패키지로 설치 하던가, 소스를 받아서 설치 하면 됨  

sudo apt-get install libtcmalloc-minimal4


* 사용하는 방법 3가지 

1. tc_malloc 및 tc_free 등의 함수를 사용하여 malloc 이나 C++의 기본 할당자를 직접 대체하는 방법


2. 라이브러리를 링크하여 C 및 C++ 기본 할당자는 대체하는 방법

TCmalloc는 라이브러리를 링크하는 것 만으로, C 및 C++의 기본 할당자를 tmalloc의 할당자로 대체 해줌.(Patch)

g++ -o mybin mybin.cpp -ltcmalloc_minimal 


3. LD_PRELOAD를 이용하여 모듈을 먼저 로드(후킹)시킨 후, 기본 할당기를 대체하는 방식 

허나 구글에서는 이 방법에 대해서는 tricky 한 방법이므로, 2번 방법을 사용 하도록 권고함

LD_PRELOAD=/usr/lib/libtcmalloc_minimal.so mybin

http://gperftools.googlecode.com/git/doc/tcmalloc.html

 

* 성능 

- 극단적인 할당과 해제를 반복하는 멀티쓰레드 환경에서, 기본 할당자 보다 3배이상 빠른 결과를 보임

- 물론 일반적인 로직의 경우 메모리 할당, 해제에 관련해서 비중이 얼마나 많이 차이나느냐에 따라 다르겠지만, 메모리 할당에서의 성능 향상 뿐만 아니라, 지속적이 서비스로 인한 메모리 단편화를 감소시켜 바꾸는 것만으로 20% 정도의 성능 향상을 보인 다고 함.

  


# 윈도우 환경에서의 TCmalloc 

- 소스 받아서 MSVC로 설치 하면 됨. 친절하게 MSVC 프로젝트 파일로 제공 됨  

- 솔루션에 많은 프로젝트들이 보이는데, libtcmalloc_minimal 라고 되어 있는 프로젝트만 Release 로 빌드하면, 동적링크 모듈(DLL)로 빌드되고 정적으로 바꾸고 빌드해서 사용해도 무방한 것으로..


* 사용하는 방법 2가지 

1. 위의 리눅스의 예와 같음. TCmalloc의 커스텀 할당자로 구현 하면 됨


2. 위도우 환경에서는 Patch 방식이 되지 않으므로, 라이브러리만 링크하는 것으로 끝나지는 않고 강제로 링크 심볼을 정의 함으로서 기본 할당자가 교체 되도록 설계 함 (이것도 멋짐!!)

// 소스에 아래와 같이 추가하여 라이브러리 참조 및 링크 심볼을 주입 함 

#pragma comment (lib, "libtcmalloc_minimal")

#pragma comment (linker, "/include:__tcmalloc") 


// 프로젝트 속성 환경에서 추가 할때는,  

// 구성속성-링커-입력-추가종속성 에 명시하여 링크를 추가하고, 

// 밑에 "강제 기호 참조"에 __tcmalloc 를 넣어주면 됨


* 성능 

- 극단적인 환경에서는 30% 이상 효과가 있고, 일반적인 업무 로직에서는 그보다는 작겠지만 어느정도 성능 향상 효과가 있을 것으로 판단.

- 기본적으로 MSVC 환경에서의 메모리 할당자가 리눅스쪽의 것보다는 좋아 보임.


--


# JEMalloc 

- Jason Evans가 만들었고, 페이스북이나 파이어폭스에서 사용 한다고 함

- 성능은 TCmalloc 보다 약간 좋다고는 (주장)하나, 개인적으로 테스트 할때는 TCmalloc 보다 약간 부족 했음.

- 구글링의 결과로는 보다 다이나믹한 멀티쓰레드 환경에서 최적화 되었다는데 반복적인 할당과 해제를 반복하는 예제에서는 그다지 많은 차이를 보이지 않음.


# 리눅스 환경에서의 JEMalloc

http://www.canonware.com/jemalloc/

- TCmalloc 과 같이 소스 및 패키지 설치 지원 

sudo apt-get install libjemalloc-dev


* 사용하는 방법 

- 위의 TCmalloc과 같이 JEMalloc의 커스컴 할당기(je_malloc, je_free) 를 사용 하던가 LD_PRELOAD를 이용하여 사용하는 방법이 있음 

- JEMalloc도 링크 만으로 기본 할당자를 교체 해주나, C언어의 기본 할당자 malloc 계열만 교체 해주고 C++의 것은 교체 해주지 않음. 그래서 C++에서 사용하려면(STL 등에서) 사용자 정의 할당자를 만들고 그 곳에 JEMalloc으로 할당 하는 방식으로 처리해야 함

- 리눅스의 경우 C, C++ 할당자를 모두 교체 지원 함


- 윈도우의 경우도 링크 참조만으로 기본 할당기를 교체해주지는 않고, header 파일을 이용해서 매크로로 C언어 기본 할당자를 교체 해주는 방식으로 처리 (#include <jemalloc/jemalloc.h>)

- Mingw (gcc 4.9.2)에서는 컴파일이 잘되나, MSVC(2013) 에서는 컴파일이 몇가지 문제를 일으킴 

Github에 Win32용 포팅 버전이 있으므로 그것을 받아서 빌드 하면 됨  


# 기타

- nedmalloc : 윈도우즈 환경에 더 최적화 되었다는 nedmalloc 이런것도 있음. nedmalloc의 경우 자체 C언어 계열 커스텀 할당 함수와 C++의 allocator 를 대체할 클래스도 제공.


- tbbmalloc (Threading Building Blocks) : 인텔에서 만든 쓰레딩관련 라이브러리에 포함 되어 있는 힙 메모리 할당기 

- 사이트에서 다운 받으면 OS별 바이너리가 들어 있음.

// linux 

sudo apt-get install libtbb-dev

g++ -o mybin mybin.cpp -ltbbmalloc_proxy


// MSVC, tcmalloc 과 같은 방식

#pragma comment (lib, "tbbmalloc_proxy")

#pragma comment (linker, "/include:___TBB_malloc_proxy") 



Detours Express 3.0Detours is a library for intercepting arbitrary Win32 binary functions on x86 machines.

// 설치 후, 설치 디렉토리에서 nmake 로 빌드 후 사용 

// dll 프리로드 후킹 (Windows)

withdll.exe /d:libtcmalloc_minimal.dll mybin




# 추가, 윈도우 테스트 결과 (참고용) 

소스 : https://gist.github.com/cdecl/e7b414e8eff4a67c9396


* vc++ 기본 (msvc 2013)

[std::string alloc]

1585, 1656, 1600, 1707, 1628,

[malloc()]

1451, 1411, 1381, 1489, 1399,


* tcmalloc 

[std::string alloc]

1156, 1150, 1195, 1045, 1184,

[malloc()]

560, 586, 564, 571, 564,


* tbbmalloc (Threading Building Blocks)

[std::string alloc]

1003, 973, 963, 998, 1000,

[malloc()]

811, 782, 780, 813, 807,



# 추가, 리눅스 테스트 결과 (참고용) 

- 소스 : malloc 반복횟수 및 옵티마이저 안되게 끔 위의 소스 수정 


* 기본 (g++ 4.9.1)

[std::string alloc]

3931, 3904, 3945, 3902, 4044,

[malloc()]

1434, 1422, 1447, 1457, 1411,


* tcmalloc

[std::string alloc]

1112, 1125, 1161, 1099, 1091,

[malloc()]

355, 333, 328, 351, 334,


* jemalloc

[std::string alloc]

1451, 1442, 1396, 1427, 1411,

[malloc()]

438, 483, 432, 462, 457,


* tbbmalloc

[std::string alloc]

1856, 1843, 1820, 1868, 1842,

[malloc()]

750, 701, 765, 764, 752,



참고 : 

one malloc to rule them all

http://blog.reverberate.org/2009/02/one-malloc-to-rule-them-all.html


Scalable memory allocation using jemalloc

https://www.facebook.com/notes/facebook-engineering/scalable-memory-allocation-using-jemalloc/480222803919


Benchmarks of the Lockless Memory Allocator

http://locklessinc.com/benchmarks_allocator.shtml


C++ memory allocation mechanism performance comparison (tcmalloc vs. jemalloc)

http://stackoverflow.com/questions/7852731/c-memory-allocation-mechanism-performance-comparison-tcmalloc-vs-jemalloc

cdecl/asb 개발 중..


1. wg/wrk (Modern HTTP benchmarking tool)

- wrk는 커맨드 라인의 옵션으로, 간단한게 Http 서비스의 성능 평가를 할 수 있는 툴.

- 윈도우 환경에서도 쓸 수 있지 않을까 했지만, Linux의 aio(Asynchronous I/O)으로 구현 되어 있어 포팅 불가.

- 비슷한 툴로 Apache ab, JoeDog/siege 등이 있으며, github에 "benchmark" 등의 단어로 검색하면 더 많은 언어로 작성되어 있는 오픈소스를 찾아 볼 수 있음.


2. Boost Asio

- 윈도우 환경이라면 IOCP로 작성 가능 하겠지만, 기본적으로 작성해야 할 내용이 많고 크로스 플랫폼을 지원하고 성능적인 부분에서 검증이 되어 있는 Asio로 작성 

- boost 라이브러리는 소스 및 필요한 바이너리만 컴파일 하여 사용. (system, regex, date-time, thread) 

- regex나 thread의 경우 이미 C++11에 포함 되어 있지만 Asio 구현체가 Boost 것을 사용 함. 


3. Visual C++ 2013 

- 가장 C++11이 적합한 VC++ 컴파일러.  

- boost 및 openssl 의 경우 NuGet 으로 편하게 라이브러리를 추가해서 사용 할 수 있음. 

- boost는 NuGet의 버전이 낮고, 위에 언급한 이유로 별도로 빌드 하여 사용 함. 그리고 x64 staitc 빌드에서 crt 관련 링크 에러가 발생? 


4. g++ 4.9.1 

- ubuntu 환경에서 g++로 컴파일. 

- hyper-v 환경에서 ubuntu 14.04로 개발 테스트를 하다, 이후 14.10으로 변경. 

- g++가 문법적으로는 C++11을 VC++에 비해 더 잘 지원하는것 같으나, 기본 라이브러리가 아직 C++11에 미흡한 것들이 있음.

- std::regex 는 아직 지원을 하지 않아 boost::regex를 사용. 찾아보니 버전 5. 이상에서 지원할 것이라 추측.

- std::stringstream 의 swap 및 move ctor를 지원하지 않음.  

- OpenSSL의 경우 apt-get 패키지로 설치. 


5. Git

- 윈도우 버전의 경우 Git과 같이 배포되는 *nix 의 커맨드라인 툴이 유용함.

- tortoies-git 을 사용하는데, 몇가지 명령어는 svn 식으로 표현 된것 같음.


6. SSL (OpenSSL)

- asio에서 지원하는 ssl 코드를 사용해서 ssl 내부적인 내용까지는 구현이 필요 없었음. (다행히도..)


7. 성능 

- 환경 Laptop Intel i5(4세대), 4 Core, 8G RAM, Windows 8.1 64bit (Ubuntu 14.04 on hyper-v , 4 core, 1G RAM)  


- 윈도우 환경에서는, 최적의 옵션의 경우, IIS(local, static html) 초당 40,000 이상 호출 결과.

- 윈도우 환경 최대 연결 개수는 약 26,000 클라이언트 개수까지 테스트 

  

- Ubuntu (on hyper-v) 환경에서는, Nginx(local, static html) 호출, 초당 35,000 이상 호출 결과.

- Ubuntu 환경 최대 연결 개수를 약 30,000 클라이언트 개수까지 테스트 

- wrk 에 비해 성능이 10~20% 정도 떨어지는 것 같음. (상황에 따라 좀 다른 결과)


8. 전략 

- 기본적인 Thread 생성 개수는, 메인 + io_service 개수 + 사용자 Thread 개수가 생성이 됨

- io_service를 Thread 별로 생성을 한다면, -t 4 옵션의 경우 9개가 생성됨

- io_service는 한개만 생성하고 io_service::run() 를 사용자 Thread 에서 실행한다면, -t 4 옵션의 경우 5개 생성

- 테스트 결과 io_service per thread VS io_service::run() per thread 성능상 별 차이 없어 보여서 적게 생성되는 방향 정리.



* 기타 

- 개발 중, Http Client 모듈 수정하여 http_client 라이브러리 만듬 



cdecl/asbHttp benchmarking and load test tool for windows, posix

- wg/wrk (Modern HTTP benchmarking tool)과 기능이 비슷한, Windows 버전으로 만들게 된 커맨드 라인 툴.

- boost::asio 와 asio 에서 지원하는 ssl(openssl)을 이용하여 구현.

- VC++ 2013 환경에서 개발하고, 라이브러리 패키지 NuGet으로 관리.

- Posix 환경은 g++ (4.8 이상, -std=c++11), boost 라이브러리 및 libssl-dev (openssl) 패키지 설치  


# 테스트 결과 

- 테스트 환경 ; Laptop Intel i5(4세대), 4 Core, 8G RAM, Windows 8.1 64bit  

- 성능 좋은 결과가 나오기 위해서는 대체적으로 Core 1/2 개수의 Thread에, Core 10배수 정도의 Connection이 무난해 보임 (로컬 환경에서 테스트 할때)

성능 좋은 결과가 나오기 위해서는 대체적으로 Core 개수의 Thread에, Core 20배수 정도의 Connection이 무난해 보임

asb -d 10 -t 2 -c 40 http://localhost/index.html

> Start and Running 10s (2015-03-18.17:36:10)

  http://localhost/index.html

    40 connections and 2 Threads

> Duration         : 10000ms

    Latency        : 0.02ms

    Requests       : 426149

    Response       : 426109

    Transfer       : 147.11MB

> Per seconds

    Requests/sec   : 42610.90

    Transfer/sec   : 14.71MB

> Response Status

    HTTP/1.1 200   : 426109


# Windows 에서 최대 Connection 만들기 

- OS의 소켓 최대 포트 번호를 늘림 (초기값 : 1500, 변경: 50000)

   HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters 의 MaxUserPort 값 변경  

https://support.microsoft.com/ko-kr/kb/196271?wa=wsignin1.0

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters

편집 메뉴에서 새로 만들기를 클릭하고 다음 레지스트리 항목을 추가합니다.

값 이름: MaxUserPort

값 형식: DWORD

값 데이터: 65534

유효 범위: 5000-65534(십진수)

기본값: 0x1388(십진수 5000)

설명: 이 매개 변수는 프로그램이 시스템에서 사용 가능한 사용자 포트를 요청할 때 사용되는 최대 포트 번호를 제어합니다. 일반적으로 수명이 짧은 임시(ephemeral) 포트에는 1024에서 5000 사이의 값이 할당됩니다. 보안 공지 MS08-037 릴리스 후 Windows Server 2003의 동작이 Windows Server 2008 및 Windows Vista의 동작과 보다 근접하게 일치하도록 변경되었습니다. Microsoft 보안 공지 MS08-037에 대한 자세한 내용은 다음 문서 번호를 클릭하여 Microsoft 기술 자료 문서를 참조하십시오.

- IIS의 응용프로그램의 큐 길이를 늘림 (초기값 : 1000, 변경: 3000), Worker Thread 개수 늘림 (초기값: 1, 변경: 2)

- IIS의 경우, 경로를 http://localhost/ 이렇게 줘서 Default 파일을 찾는 과정이 생각보다 느림 (20% 성능)

- 현재 조건(랩탑)에서는 최대 26,000 연결 정도 까지 가능하고 27,000 연결 이상 테스트 하면 문제가 발생함 (리소스가 부족한 것으로 추측)

- http://sockettools.com/kb/maximum-socket-connections/

asb -d 20 -t 3 -c 26000 http://localhost/index.html
> Start and Running 20s (2015-03-18.18:14:41)
  http://localhost/index.html
    26000 connections and 3 Threads
> Duration         : 20038ms
    Latency        : 0.09ms
    Requests       : 239424
    Response       : 213426
    Transfer       : 76.26MB
> Per seconds
    Requests/sec   : 10671.30
    Transfer/sec   : 3.81MB
> Response Status
    HTTP/1.1 200   : 213426




# Ubuntu 에서 최대 Connection 만들기 
- 테스트 환경 : Ubuntu 14.04 on hyper-v , (4 core, 1G RAM)
- 현재 상태 확인 : ulimit -a       
- OS의 소켓(파일) 개수를 늘려 줌 (/etc/security/limits.conf 파일 수정)
# 추가 
*               soft    nofile            65535
*               hard    nofile            65535
*               soft    nproc            65535
*               hard    nproc            65535
 
- nginx 설정 수정 
# nginx.conf 
worker_processes auto;
worker_rlimit_nofile 100000;
 
events {
    # worker_connections 1024;
    # 1024 x 16 
    worker_connections 16384;
    use epoll;
    multi_accept on;
}

# sites-available/default
# 모니터링용 페이지 노출 
location /nginx_status {
# Turn on stats
stub_status on;
access_log   off;
# only allow access from 192.168.1.5 #
# all
allow all;
}

- 클라이언트의 운영방식 인지, 서버의 운영방식 때문인지는 모르겠지만 4000 이상은 안올라 가는 것 같음 ( wrk 도 비슷한 결과 )
- 가상머신 임에도 불구하고, 30,000 연결 까지는 가능한 듯 (nginx 작업 프로세스 수 변경). 물론 처리량은 형편없이 떨어지지만.. 
- 이론상 서버 연결 가능한 수 :  worker_connections x worker_processes = 16384 x 4 = 65536
asb$ asb -d 20 -t 3 -c 30000 http://localhost/index.html
> Start and Running 20s (2015-03-18.14:50:05)
  http://localhost/index.html
    30000 connections and 3 Threads
> Duration         : 68805ms
    Latency        : 2.49ms
    Requests       : 56867
    Response       : 27585
    Transfer       : 28.10MB
> Per seconds
    Requests/sec   : 1379.25
    Transfer/sec   : 1.40MB
> Response Status
    HTTP/1.1 200   : 27585



# http://localhost/nginx_status 
Active connections: 30002 
server accepts handled requests
 30010 30010 36553 
Reading: 0 Writing: 1 Waiting: 30001 


+ Recent posts