반응형

보통 어플리케이션 CPU, Load Average가 비정상적으로 높게 튈 때

스레드덤프(thread dump)를 떠서 많이들 보실 텐데요.

jstack PID > 파일명.dump

이렇게 생성된 dump파일을 콘솔에서 분석하기는 매우 힘이듭니다.

이런 덤프파일을 무료로 분석해주고 이쁜(?) 시각화까지 진행해주는 사이트 공유드립니다.

https://fastthread.io

 

fastthread.io

Beyond APM Application Performance Monitoring (APM) tools are great at telling that your application's CPU spiked up by x%, your memory degraded by y%, your response time increased by z milliseconds. But it won't tell you what caused the CPU to spike? what

fastthread.io

해당 사이트에 들어가셔서 dump뜬 파일을 업로드 해주시기만 하면

다음과 같이 분석된 자료를 보기좋은 UI를 통해 제공받으실수 있습니다.(Time Waiting 안습 ㅠ.ㅠ, 분석도중 올립니다)

 

그럼 저는 다시 분석하러~뿅~!

반응형
반응형

Shell Script에서 특정 날짜 조건으로 배치성 작업을 처리할 일이 있어 원하는 날짜 범위에 맞게 처리되는지 확인하기 위해

 

다음과 같이 찍어보았다.

#!/bin/bash

for i in `seq 0 30`; do
        echo `date + %Y%m%d -d "20190322 -$i days"`; done

쉘스크립트를 실행해보면 

date: extra operand `%Y%m%d'
Try `date --help' for more information.

다음과 같이 뜬다.

 

문제는 date +%Y%m%d 시에 '+'와 날짜포맷사이에 공백이 있으면 안된다!!!

echo `date +%Y%m%d -d "20190322 -$i days"`; done

$ sh batch_conv_buy_insert.sh
20190401
20190331
20190330
20190329
20190328
20190327
20190326
20190325

원하는 범위의 date가 출력되는 것을 확인할 수 있다.

반응형
반응형

스프링부트 프로젝트 생성 후 어플리케이션을 실행시켰는데 에러없이 실행되자마자 종료되는 경우가 있다. 

 


Process finished with exit code 0

라고 뜨며 어플리케이션이 바로 종료되어버린다.

스프링부트는 임베디드톰캣 기반으로 실행되는데 임베디드컨테이너의 클래스패스를 못잡아줘서 그런 것 같다.

따라서 메이븐에 다음과 같이 의존성을 추가해준다.

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-web</artifactId>

</dependency>

<dependency>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-web</artifactId>

</dependency>

 

반응형
반응형


클린코드 책에서 읽은 '깨끗한 테스트코드 5가지 규칙(FIRST)'에 대해 포스팅 남겨보겠습니다.


프로그래밍을 할 때 어떻게 보면 테스트 코드의 작성은 가장 기본이면서 중요하다고 할 수 있는데요.


TDD방식의 프로그래밍까지는 아니더라도 테스트코드를 작성해주면 서비스에서의 버그를 확실히 줄여줄 수 있고


기능 추가시에도 빠르게 테스트해보고 적용하는 등 이점을 많이 가지고 있는데요. 


그렇다면 어떠한 기준과 방식으로 테스트코드를 작성해야하는지 5가지 규칙을 보시도록 하겠습니다.


[클린코드] 깨끗한 테스트코드 5가지 규칙(FIRST)

빠르게(Fast)
테스트는 빨라야 한다. 테스트는 빨리 돌아야 한다는 말이다. 테스트가 느리면 자주 돌릴 엄두를 못 낸다. 자주 돌리지 않으면 초반에 문제를 찾아내 고치지 못한다. 코드를 마음껏 정리하지도 못한다. 결국 코드 품질이 망가지기 시작한다.


독립적으로(Independent)
각 테스트를 서로 의존하면 안 된다. 한 테스트가 다음 테스트가 실행될 환경을 준비해서는 안 된다. 각 테스트는 독립적으로 그리고 어떤 순서로 실행해도 괜찮아야 한다. 테스트가 서로에게 의존하면 하나가 실패할 때 나머지도 잇달아 실패하므로 원인을 진단하기 어려워지며 후반 테스트가 찾아내야 할 결함이 숨겨진다.


반복가능하게(Repeatable)
테스트는 어떤 환경에서도 반복 가능해야 한다. 실제 환경, QA 환경, 버스를 타고 집으로 가는 길에 사용하는 노트북 환경(네트워크가 연결되지 않은)에서도 실행할 수 있어야 한다. 테스트가 돌아가지 않는 환경이 하나라도 있다면 테스트가 실패한 이유를 둘러댈 변명이 생긴다. 게다가 환경이 지원되지 않기에 테스트를 수행하지 못하는 상황에 직면한다.


자가검증하는(Self-Validating)
테스트는 bool값으로 결과를 내야 한다. 성공 아니면 실패다. 통과 여부를 알리고 로그 파일을 읽게 만들어서는 안 된다. 통과 여부를 보려고 텍스트 파일 두 개를 수작업으로 비교하게 만들어서도 안 된다. 테스트가 스스로 성공과 실패를 가늠하지 않는다면 판단은 주관적이 되며 지루한 수작업 평가가 필요하게 된다.


적시에(Timely)
테스트는 적시에 작성해야 한다. 단위 테스트는 테스트하려는 실제 코드를 구현하기 직전에 구현한다. 실제 코드를 구현한 다음에 테스트 코드를 만들면 실제 코드가 테스트하기 어렵다는 사실을 발견할지도 모른다. 어떤 실제 코드는 테스트하기 너무 어렵다고 판명날지 모른다. 테스트가 불가능하도록 실제 코드를 설계할지도 모른다.


규칙 하나하나 너무나도 중요한 얘기들인 것 같습니다. 이 규칙을 염두해두시고 프로그래밍을 하신다면

좀 더 안정적인 서비스를 하시는데, 작성한 코드를 테스트하는데 드는 시간을 많이 줄일 수 있을 것 같습니다!

반응형
반응형



HashMap을 생성하고 그 안에 put을 해도 HashMap자체의 해쉬코드(hashCode)값은 안변할 줄 알았것만.....


결론은 put을 할 때마다 hadhCode값이 변하게 됩니다.


[ 백문이불여일코딩 ]


[ 결과 hashcode 값 ]

get메서드사용할때는 당연히 안바뀌고 put으로 데이터를 넣을 때 마다 해쉬코드가 변하는 것을 확인!!!!

값은 key값에 데이터를 덮어씌울때도 hashcode가 변한다! 이유는??


[ 이유는??? ]

HashMap의 put메서드가 내부적으로 entry를 새로 만들기 때문!!!!

map에서의 hashcode의 값은 entry의 해시코드의 합으로 정의되는데 내부에서 

put메서드가 호출될때마다 새로운 entry를 생성하기 때문에 값이 달라짐

public int hashCode()
Returns the hash code value for this map. The hash code of a map is defined to be the sum of the hash codes of each entry in the map's entrySet() view. This ensures that m1.equals(m2) implies that m1.hashCode()==m2.hashCode() for any two maps m1 and m2, as required by the general contract of Object.hashCode().

This implementation iterates over entrySet(), calling hashCode() on each element (entry) in the set, and adding up the results.

Specified by:
hashCode in interface Map<K,V>
Overrides:
hashCode in class Object
Returns:
the hash code value for this map
See Also:
Map.Entry.hashCode(), Object.equals(Object), Set.equals(Object)


참조 : https://docs.oracle.com/javase/7/docs/api/java/util/AbstractMap.html#hashCode()


[ HashMap put메서드를 따라가보자! ]

1. put


2. putVal


3. putTreeVal


4. newTreeNode


5. new TreeNode



6. TreeNode의 super


Wow....


상식적으로 생각했을 때 Map이 한 번 생성되면 안에 내용이 변경되더라도 해시코드(hashcode)값은 변하지 않을 줄 알았는데....


변하는 것을 보고 한 번 끝까지 따라가 보았다.


뭔가 속이 후련한???


앞으로도 궁금한점이 생긴다면 대충 알고 넘어가는 것보다 한 번 끝까지 따라가 제대로 된 이유를 알아보는것을 습관화하도록 하자!






반응형
반응형

요즘 Superset을 통해 데이터 시각화하는 작업을 진행중인데요. 


해당 오픈소스 클라이언트 쪽을 혹시나 커스터마이징 해야할 일이 있을까 싶어 일단 로컬환경에 셋팅하며 세팅한 내용 포스팅 남겨봅니다.



먼저 SuperSet이란?

Apache프로젝트에 속한 오픈소스 데이터 시각화 툴이고 굉장히 깔끔한 UI와 다양한 차트들을 제공합니다.

깃 레파지토리(Git repo)



Superset 설치

git clone https://github.com/test/test.superset.git
cd test.superset
# Create a virtual environemnt and activate it (recommended)
# 이 부분은 사용하는 IDE에 따라서 자동으로 해주는 경우가 있습니다.
virtualenv venv
source venv/bin/activate
# Install external dependencies
pip install -r requirements.txt
pip install -r requirements-dev.txt
# 해당 명령어 수행시 해당 문제가 발생한 경우 
fatal error: too many errors emitted, stopping now [-ferror-limit=]
    20 errors generated.
    error: command 'clang' failed with exit status 1
    ----------------------------------------
Command "/Users/nhnent/IdeaProjects/[[dighty.superset/venv/bin/python3.7&#93;\(http://dighty.superset/venv/bin/python3.7\)](http://dighty.superset/venv/bin/python3.7](http://dighty.superset/venv/bin/python3.7)) -u -c "import setuptools, 
tokenize;__file__='/private/var/folders/72/tlj3dkwx5vx_4tvvmkt9v3nm0000gn/T/pip-install-5sa870m3/thriftpy/setup.py';f=getattr
(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" 
install --record /private/var/folders/72/tlj3dkwx5vx_4tvvmkt9v3nm0000gn/T/pip-record-0derjrrg/install-record.txt 
--single-version-externally-managed --compile --install-headers 
/Users/nhnent/IdeaProjects/[[dighty.superset/venv/bin/../include/site/python3.7/thriftpy&#93;\(http://dighty.superset/venv/bin/../include/site/python3.7/thriftpy\)](http://dighty.superset/venv/bin/../include/site/python3.7/thriftpy](http://dighty.superset/venv/bin/../include/site/python3.7/thriftpy))" failed with error code 1 
in /private/var/folders/72/tlj3dkwx5vx_4tvvmkt9v3nm0000gn/T/pip-install-5sa870m3/thriftpy/
>> pip3 install cython thriftpy  (해당 명령어 실행 후 다시 실행)
pip install mysqlclient
# 위 설치 과정 중 mysqlclient에 문제가 발생한 경우
# https://www.lfd.uci.edu/~gohlke/pythonlibs/ 로 접속하여,  
# 본인의 윈도우 시스템과 python 버전에 맞는 .whl파일 다운로드
# 나의 경우(MAC) > macholib‑1.11‑py2.py3‑none‑any.whl  다운 받음
# pip install [다운받은 whl파일 경로]
# Install Superset in editable (development) mode
pip install -e .
# Create an admin user
fabmanager create-admin --app superset


cd dighty.superset/venv/bin
# Initialize the database python superset db upgrade # Create default roles and permissions python superset init # Load some data to play with python superset load_examples
cd dighty.superset/superset

# Start the Flask dev web server from inside the `superset` dir at port 8088
# Note that your page may not have css at this point.
# See instructions below how to build the front-end assets.
# 해당 flask 명령어 수행 이후 npm 명령어 실행 시켜줘야 css가 안깨짐

flask run -p 8088 --with-threads --reload --debugger

flask 서버만 띄우면 다음처럼 css가 다깨지기때문에 flast서버 띄워논 후 npm으로 빌드해서 dev-server를 띄워준다.


npm run dev-server


짜잔~~~


또 Superset을 사용하다가 삽질한 부분이 생기게 되면 포스팅해보도록 하겠습니다.


Superset 흥해라~!!!

반응형
반응형


맥(MAC)에서 GIF를 쉽게 만들 수 있게 도와주는 앱을 소개합니다.


앱이름은 

GIPHY Capture. The GIF Maker

입니다.


사용법은 아주 간단합니다. 먼저 다운을 받고 설치한 후 실행하면 다음과 같이 창이 열립니다.


해당 창안에서 녹화되는 부분이 GIF로 생성되게 됩니다.


빨간 버튼을 눌러 녹화를 해주면 끝^^



감사합니다:)








반응형
반응형

오늘은 파티셔닝에 대해서 포스팅 해보도록 하겠습니다. 실제로 파티셔닝으로 테이블을 설계해 보지 않아서 대략적인 의미만 알고 있었기에 한 번 정리할겸 책에서 학습한 내용을 정리해 봅니다. 해당 내용은 '관계형 데이터베이스 실전 입문'을 참고하였습니다. 


파티셔닝(Partitioning)이란?

파티셔닝에는 일반적으로 수평 파티셔닝(행으로 파티션을 나누는 방식) 수직 파티셔닝(컬럼별로 파티셔닝을 나누는 방법, 특정 컬럼만을 고속 스캔할 때 유용) 두 가지 방법이 있다. 보통 일반적으로 수평 파티셔닝(행으로 파티션을 나누는) 방식을 대부분 사용하고 해당 포스팅에서도 수평 파티셔닝에 대해서만 정리하도록 하겠습니다.


인덱스는 임의의 키 값에 따라서 행 데이터의 위치를 식별하는데 사용하는 기능인 반면 파티셔닝은 테이블을 여러 개의 파티션으로 분할하고 키의 값에 따라 어떤 파티션에 속하는 행인지 배분하는 역할을 합니다. 

파티션은 각각 같은 구조(schema)를 가진 테이블이며 인덱스도 파티션마다 존재합니다.

출처 : 관계형 데이터베이스 실전 입문


위의 그림에서는 세 개의 파티션이 정의되어 있고 날짜에 따라 저장될 파티션이 나뉘게 됩니다. 어떤 파티션에 속할 것인지 정하는 키(파티션 키)를 검색 조건으로 지정하면 해당 파티션만 검색하면 되므로 검색 효율이 향상됩니다. 

위의 그림에서 검색조건이 '2014-04-01'이므로 p3 파티션에 원하는 행이 있다는 사실을 알 수 있습니다. 이처럼 검색 대상 파티션을 좁혀가는 동작을 파티션 프루닝(Partition Pruning)이라고 합니다. -> Pruning은 가지치기란 뜻입니다.



파티셔닝이 적합한 경우

파티셔닝을 사용할지의 가장 큰 판단 기준은 파티션 프루닝을 할 수 있는 검색 조건을 포함한 쿼리의 실행빈도입니다. 파티션 프루닝이 유효한 쿼리가 대부분일 때는 파티셔닝에 의한 처리 전체의 효율화가 기대됩니다. (일반적으로 날짜를 기준으로 최신 데이터를 항상 참조할 경우)


그러나 파티셔닝이 적합하다고 판단될 때도 인덱스를 붙이는 것만으로 충분할 때가 대부분입니다. 파티셔닝을 사용하는 이유는 단일 INSERT나 혹은 단일 Select, 범위 Select의 아주 빠른 처리가 필요할 경우 혹은 이력 데이터의 효율적인 관리가 필요한 경우 입니다. (불필요해진 데이터를 백업 & 삭제하는 작업이 상당히 고부하 작업이기 때문)


추가로 새로운 데이터를 차례로 추가하는 응용프로그램이며 과거의 데이터에 그다지 접근하지 않을 때는 레인지 파티셔닝을 수행해 엑세스되는 대상의 데이터 국소성을 최대한 활용할 수 있다. 파티셔닝을 사용하면 파티셔닝별로 인덱스가 작성되기 때문이다.  최신 데이터가 항상 검색 대상이라면 p3(그림)만 엑세스 대상이 될 것이고 엑세스의 국소성이 있다면 캐시의 효율이 매우 향상된다. 따라서 대부분 검색이 메모리만으로 처리되고 디스크 I/O를 줄여서 성능 향상을 실현 할 수 있다. 


파티셔닝의 단점

데이터를 입력받았을 경우 어디에 넣어야 하는지에 대한 연산 오버헤드가 발생 할 수 있고 인덱스만으로도 해결되는 부분 파티셔닝을 무분별하게 파티셔닝을 적용했을 때는 오히려 성능이 나빠질 수 있음에 유의.



결론

파티셔닝을 적용할 때는 적용하지 않았을 때와 비교해 확실한 성능의 이점이 생기는지 꼭 확인해보자!!!!


반응형
반응형


Heap Dump를 볼 일이 생겨서 Eclipse Memory Analyzer(MAT) 설치 후 실행을 하려고 하는데 다음과 같은 에러가 발생하였다.


'An error has occurred. See the log file~~~'



그래서 해당 위치에 가서 log파일을 열어 보니 다음과 같은 에러가 발생한 상태였다...


!SESSION 2019-01-31 16:45:23.495 -----------------------------------------------

eclipse.buildId=unknown

java.version=1.8.0_151

java.vendor=Oracle Corporation

BootLoader constants: OS=macosx, ARCH=x86_64, WS=cocoa, NL=ko_KR

Framework arguments:  -keyring /Users/nhnent/.eclipse_keyring

Command-line arguments:  -os macosx -ws cocoa -arch x86_64 -keyring /Users/nhnent/.eclipse_keyring


!ENTRY org.eclipse.osgi 4 0 2019-01-31 16:45:27.178

!MESSAGE Application error

!STACK 1

java.lang.IllegalStateException: The platform metadata area could not be written: /private/var/folders/72/tlj3dkwx5vx_4tvvmkt9v3nm0000gn/T/AppTranslocation/2AB9061A-0D7D-4CE6-AA94-5D14138D7687/d/mat.app/Contents/MacOS/workspace/.metadata.  By default the platform writes its content

under the current working directory when the platform is launched.  Use the -data parameter to

specify a different content area for the platform.

        at org.eclipse.core.internal.runtime.DataArea.assertLocationInitialized(DataArea.java:70)

        at org.eclipse.core.internal.runtime.DataArea.getStateLocation(DataArea.java:138)

        at org.eclipse.core.internal.preferences.InstancePreferences.getBaseLocation(InstancePreferences.java:44)

        at org.eclipse.core.internal.preferences.InstancePreferences.initializeChildren(InstancePreferences.java:209)

        at org.eclipse.core.internal.preferences.InstancePreferences.<init>(InstancePreferences.java:59)

        at org.eclipse.core.internal.preferences.InstancePreferences.internalCreate(InstancePreferences.java:220)

        at org.eclipse.core.internal.preferences.EclipsePreferences.create(EclipsePreferences.java:349)

        at org.eclipse.core.internal.preferences.EclipsePreferences.create(EclipsePreferences.java:337)

        at org.eclipse.core.internal.preferences.PreferencesService.createNode(PreferencesService.java:393)

        at org.eclipse.core.internal.preferences.RootPreferences.getChild(RootPreferences.java:60)

        at org.eclipse.core.internal.preferences.RootPreferences.getNode(RootPreferences.java:95)

        at org.eclipse.core.internal.preferences.RootPreferences.node(RootPreferences.java:84)


구글링 결과 zip압축파일을 푼 실행파일의 위치를 Applications폴더로 이동시켜주어 해결했다는 글을 발견!!!


이에 바로 Documents폴더에서 Applications폴더로 이동 후 실행하니 정상적으로 실행되었다~


혹시나 같은 문제가 발생하시는 분들은 폴더 이동시켜서 실행해보세요:)


반응형

+ Recent posts