manywaypark's Blog
개발, 검색, 함수

~/.Xdefaults file:
Emacs.FontBackend: xft
Xft.dpi: 96
Xft.hinting: None
Emacs.font:UnTaza-16

$ xrdb -merge ~/.Xdefaults

emacs-snapshot 에서만 동작을 확인했음.

happy hackin'

[BR] EUnit Bug Report

함수형 언어/Erlang 2008. 12. 24. 18:25 by manywaypark
맨 마지막 테스트 함수의 테스트 준비단계가 2번 실행되는 버그가 있는 것같다.
나의 test case가 성공할 때도 있고 실패할 때도 있는 이상한 상태가 되어서 내 잘못인 줄 알고 개발중인 모듈의 여기저기를 손댔다가 갑자기 느끼는 바가 있어 EUnit을 테스트하는 간단한 코드를 만들었다.

일단 공식적으로 버그 리포트는 했고,
참고를 위해 글을 남긴다.

last_test_() ->
do_some_prep(), % 요놈이 매번 두번씩 불린단 말씀.
... do some tests ...
do_some_prep()가 두번 불려지면 당혹스런(?) 테스트 실패가 나올 수 있다. disk i/o나 DB operation 처럼 side effect가 있는 경우에 특히 테스트가 통과될 때도 있고 안될때도 있는 불안정한 상태가 될 수 있다.

happy hackin'

ps. 글을 쓰고 좀더 만져 보니 조금 더 복잡하다. EUnit 사이트에 올린 케이스들 말고 테스트 케이스를 다음과 같이 하면...

twice_case1_test_() ->
    io:format("c1: prep one~n"),
    ?_assert(1 + 1 =:= 2).

twice_case2_test_() ->
    io:format("c2: prep one~n"),
    ?_assert(1 + 1 =:= 2).

twice_case3_test_() ->
    io:format("c3: prep one~n"),
    ?_assert(1 + 1 =:= 2).

결과:
(emacs@desktop)14> eunit_twice_case:test().
c3: prep one
c2: prep one
c3: prep one
c2: prep one
c1: prep one
  All 3 tests successful.
ok
마지막에 있는 두개가 두번씩 불린다.

2008-12-31 "by design" 이라는군요 Orz. side effect가 있는 함수는 준비단계에서 부르면 절대 안되겠습니다.
Erlang:
시퍼렇게 날이 선,
언제라도 목표가 포착되면 일도양단의 기세로 칼집에서 뛰쳐나올듯한 예리한 刀와 같은...

Lisp:
약간은 뭉툭한,
시간을 가지고 연마하면 그 어떤 치명적인 무기로도 바뀔 수 있는 연철(軟鐵)과 같은...

그렇다. Erlang은 Lisp을 오랜 기간 연마하여 탄생한 Joe의 치명적 무기다.

happy hackin'

이직

잡담 2008. 12. 6. 13:38 by manywaypark
다가오는 새해에는 다른 회사로 출근한다.
누구의 추천도, 아무런 인맥도 없는 곳에 지원했고 얼마전 세부 협상까지 마쳤다.

편견도 기득권도 없다.
이런 조건으로의 이직을 한번도 안했었다는 생각이 문득 들었다.
(모든 경우에 이직하는 회사에 잘 알고 있는 사람이 있거나 추천이 있었다)
무언가 기득권을 바라고 있었던 것인가? 자신감이 없었나?

신규 팀을 하나 맡을 것같다.
최근의 고민과 생각들을 바탕으로 활력 넘치는 팀으로 꾸려나가고싶다.

이제, 새 회사로 출근하기만 하면된다.

happy hackin'
제목의 용어가 정확한지 잘 모르겠다. 작업도중 필요해서 만들게 되었는데 함수형 언어의 장점(REPL의 장점)을 부각시킬 수 있는 예제가 될 수 있을 것같아서 포스팅한다.
전각 문자를 반각으로 문자열 변환하는 간단한 함수를 하나 만들었는데 좀 꼼수(?)를 동원해서 얄팍하게 재빨리 만들었다.
정확하게 하려면 몇몇 자료를 참조해야하겠지만, 필요한 상황의 테스트 케이스는 다 통과하므로 그대로 쓰기로 했다.

(emacs@desktop)1> "ABC012". % wide chars
"\357\274\241\357\274\242\357\274\243\357\274\220\357\274\221\357\274\222".
[239,188,161,239,188,162,239,188,163,239,188,144,239,188,
 145,239,188,146]
(emacs@desktop)2> "A".         % wide char
"\357\274\241".
(emacs@desktop)3> "A".          % normal char
"A"
(emacs@desktop)4> "0".         % wide char
"\357\274\220".
[239,188,144]
(emacs@desktop)5> $0.           % normal char
48

패턴이 보이는가?
[239,188] ("\357\274") 뒤의 숫자만 변한다. ^^;
자연스럽게 다음과 같은 함수가 만들어진다.
%% 96 = last("1") - $1
'wide->narrow'([239,188,C|T]) ->
    [C - 96 | 'wide->narrow'(T)];
'wide->narrow'([C|T]) ->
    [C | 'wide->narrow'(T)];
'wide->narrow'([]) ->
    [].

결과:
(emacs@desktop)8> str_util:'wide->narrow'("ABC012").
str_util:'wide->narrow'("\357\274\241\357\274\242\357\274\243\357\274\220\357\274\221\357\274\222").
"ABC012"

REPL이 지원되지 않는 언어였더라면 과연 이렇게 눈깜짝할 사이에 만들 수 있었을까?
단위 작업의 feedback이 즉시 확인되는 것은 엄청난 매력이자 장점이다.

happy hackin'
좀 복잡한 테스트 케이스를 하나 추가하고 컴파일후 mod:test()를 실행했더니,
다음과 같은 에러가 나면서 그 모듈에 대한 유닛 테스트가 아예 동작하지 않았다.
*** test module not found ***
::false

{error,{module_not_found,false}}

순간 당황했으나, 방금 추가한 테스트 케이스를 살펴보니 _assert macro에 들어가는 내용이 잘못되어 있었다. boolean expression이 들어가야하는 곳에 그냥 expression만 하나 들어있었고, _assert(very_complex_expression) =:= expected value의 형태로 되어 있었다(어제 급히 추가하고 안돌려보고 바로 퇴근한 것이 후회되는 순간이었다). 그래도 컴파일은 멀쩡히 평소처럼 잘 되고 runtime에 가서야 에러가 나는 것은 좀 불편해보인다.

간략히 축약해서 예를 들자면 다음과 같다.
%% causes runtime error (see above msg).
?_assert(1+1) =:= 2
%% runs well w/o runtime error (good)
?_assert(1+1 =:= 2)

실제 내 코드에서는 1+1부분이 많이 복잡해서 화면을 넘어가고 있었고, _assert macro가 여러 개의 리스트로 묶여져 있어서 찾는데 좀 고생했다. Orz.

happy hackin'

[UTIL] scponly - 설치

tips & tricks/Linux/Unix 2008. 9. 21. 23:44 by manywaypark
환경 : ubuntu(64bit), x86-84
ssh 프로토콜만을 사용해서 sftp만 독립적(?)으로 실행하는, 안전한 scponly를 설치하는 방법을 설명한다.[각주:1]
ubuntu package를 설치하는 것만으로는 좀 미진한 부분이 있어 추가 설정에 관해서 알아본다. 
  1. root 권한으로 로그인후에,
  2. scponly package를 설치한다
    # apt-get install scponly
  3. 설정 스크립트 압축 풀기
    # cd /usr/share/doc/scponly/setup_chroot/
    # gzip -d setup_chroot.sh.gz
  4. 설정 스크립트(setup_chroot.sh) 편집 (64bit 시스템만 해당)
    다음과 비슷한 라인을 찾아서,
    LDSO_LIST="/lib/ld.so /libexec/ld-elf.so /libexec/ld-elf.so.1 /usr/libexec/ld.so /lib/ld-linux.so.2 /usr/libexec/ld-elf.so.1"
    다음과 같이 변경(ld-linux-x86-64.so.2 추가)
    LDSO_LIST="/lib/ld.so /libexec/ld-elf.so /libexec/ld-elf.so.1 /usr/libexec/ld.so /lib64/ld-linux-x86-64.so.2 /lib/ld-linux.so.2 /usr/libexec/ld-elf.so.1"
  5. 설정 스크립트 실행
    # sh ./setup_chroot.sh
    username, user_home_dir,  user_working_dir(요건 user_home_dir 밑에 위치하게 설정) 입력.
  6. /etc/shells에 scponlyc 추가
    which scponlyc >> /etc/shells
  7. SUID-Bit 설정
    chmod u+s `which scponlyc`
  8. dev 만들기
    # cd /home/username
    # mkdir dev
    # cd dev
    # mknod -m 666 null c 1 3
  9. sftp로 접속해서 파일 upload, download 테스트하기. 잘 안되면 다음 명령어로 debug message 확인해보기
    echo 2 /etc/scponly/debuglevel

참고: 

happy hackin'
  1. 참고 사이트 정리에 불과하다. :) 우분투 x86-64에 설치할 때를 기준으로 좀 편리하게 정리했다. [본문으로]
외부 DTD 파일에 <?xml version ... ?> 같은 XML 파일임을 나타내는 PI가 들어있으면 xmerl_scan:(file|string)에서는 다음과 같은 에러를 내면서 parsing이 안된다 (java 쪽에서는 별 문제가 없었던 DTD 파일이다).

error msg:
1066- fatal: {invalid_target_name," version=\""}
** exception exit: {fatal,{{invalid_target_name," version=\""},
                           {file,"/path/to/dtd.dtd"},
                           {line,6},
                           {col,18}}}
     in function  xmerl_scan:fatal/2
     in call from xmerl_scan:scan_ext_subset/2
     in call from xmerl_scan:scan_decl_sep/2
     in call from xmerl_scan:scan_ext_subset/2
     in call from xmerl_scan:scan_decl/2
     in call from xmerl_scan:fetch_and_parse/3
     in call from xmerl_scan:fetch_DTD/2
     in call from xmerl_scan:scan_doctype2/3

간편 해결책: DTD 들이 있는 디렉토리에서 다음을 실행해주자 (DTD 파일이 여러개일때...)
$ sed -i -r "/<\?xml .*\?>/s/.*//" *.dtd      # remove xml PI stuff.
$ sed -i '/./,/^$/!d' *.dtd                   # remove leading blank line(s).

happy hackin'
파일이 삼천만개면 너무 많은 건가? --;

파일들의 개수가 많아지면, 참기 힘들 정도로 속도가 저하된다.
apt-get 등으로 정상적인 시스템 관리(package update 등)하기도 너무 느려서 짜증날 정도다.

관리의 편의를 위해 많은 삽질 끝에 자동으로 대량의 데이터 파일들을 .deb 파일로 만들어서 간편하게 설치하는 방식을 현재 진행중인 프로젝트에 적용했으나, 속도 문제로 다른 방법을 찾아야할 듯하다.

예:
# dpkg -r some-pkg
(Reading database ... 36070717 files and directories currently installed.)
Removing some-pkg ...

위에 보이는 패키지 하나 삭제하는 데에 몇십분은 걸리는 듯하다. Orz.

happy hackin'




ko:
성능을 향상 시키는 방법:
  1. 메모리 사용량을 낮게 유지한다.
  2. CPU 사용률을 높게 유지한다.
  3. 한계를 넘어서지 않는 한 많은 수의 worker 를 동작시킨다. (2번을 실제 적용하는 유용한 방법중의 하나).
  4. 실행 흐름을 동기화가 필요하지 않은 방향으로 설계한다 (spawn후에 잊어버리기 전략. 3번과 일맥상통).

en:
to improve performance of concurrent program:
  1. always keep small footprint of memory usage.
  2. high CPU utilization.
  3. run workers as many as possible (of course, under limit). one of good methods for #2.
  4. design program flow to avoid synchronization. use spawn and forget strategy if possible.

happy hackin'
1 ··· 21 22 23 24 25 26 27 ··· 31 
분류 전체보기 (306)
잡담 (20)
함수형 언어 (65)
emacs (16)
java (18)
tips & tricks (154)
사랑 (1)
가사 (0)
독서 (4)
mobile (6)
비함수형 언어 (2)

공지사항

최근에 올라온 글

최근에 달린 댓글

최근에 받은 트랙백

03-29 16:00