숫자 넣어 때려 맞추기

누군가 a t + b sin( c t ) = d 의 해를 어떻게 구할까 라고 질문을 올렸다.
http://kldp.org/node/112110

허리도 아프고 퇴근시간도 거의 다 되었고 해서 잠시 생각해 보았다.
at + bsin(ct) = d
bsin(ct) = d - at
sin(ct) = (d - at) / b
Therefore, |(d-at)/ b| <= 1
-1 <= (d - at)/b <= 1
if b>0
-b <= d - at <= b
-b + d <= at <= b + d
if a>0
(-b + d)/a <= t <= (b + d)/a

여기서 f(t) = at + bsin(ct) -d 라고 하고
N 개로 잘라내서 f(t) 의 부호가 바뀌는 걸 확인한다면,
전체 길이가 (b + d)/a - (-b + d)/a = 2b /a
따라서 단위 t 의 길이는 ( 2b / a )/N

Java 로 만든 코드
몇몇 결과
(a, b, c, d) = (1, 1, 1, 1) 이고 N 이 10 이라면

a 1.000000 b 1.000000 c 1.000000 d 1.000000
 F(0.000000)= -1.000000
 F(0.200000)= -0.601331
 F(0.400000)= -0.210582
 F(0.600000)= 0.164642
 F(0.800000)= 0.517356
 F(1.000000)= 0.841471
 F(1.200000)= 1.132039
 F(1.400000)= 1.385450
 F(1.600000)= 1.599574
 F(1.800000)= 1.773848
 F(2.000000)= 1.909297

따라서 대충 0.4 ~ 0.6 사이에 있을 듯.

좀 더 정확히 하기 위해 N 을 100 으로 했더니
... 생략
 F(0.480000)= -0.058221
 F(0.500000)= -0.020574
 F(0.520000)= 0.016880
 F(0.540000)= 0.054136
... 생략

고로 대충 0.5xx 인 것 처럼 보인다.

하나 더,
(a, b, c, d) = (1, 2, 3, 4) 이고 N 이 20 이라면
a 1.000000 b 2.000000 c 3.000000 d 4.000000
 F(2.000000)= -2.558831
 F(2.200000)= -1.176917
 F(2.400000)= -0.012664
 F(2.600000)= 0.597087
 F(2.800000)= 0.509198
 F(3.000000)= -0.175763
 F(3.200000)= -1.148654
 F(3.400000)= -1.999749
 F(3.600000)= -2.361872
 F(3.800000)= -2.038657
 F(4.000000)= -1.073146
 F(4.200000)= 0.267246
 F(4.400000)= 1.584147
 F(4.600000)= 2.487391
 F(4.800000)= 2.731316
 F(5.000000)= 2.300576
 F(5.200000)= 1.415507
 F(5.400000)= 0.455156
 F(5.600000)= -0.175134
 F(5.800000)= -0.185319
 F(6.000000)= 0.498026

이건 대충 2.4~2.5 와 2.8 ~ 3.0, 그리고 4.0 ~ 4.2, 5.4 ~ 5.6, 5.8 ~ 6.0 사이에 있겠구만.

Posted by eoh

2010/01/26 19:34 2010/01/26 19:34
, ,
Response
No Trackback , No Comment
RSS :
http://endofhope.com/tc/rss/response/21

신경쇠약 프로젝트

지금까지 내 경험과 지식을 정리하여 네트워크 프레임워크를 하나 만들었다.
Neurasthenia 라고 이름붙이고 LGPL로 공개했다.
이런 이름을 붙인 이유는 comet 이란 것이 세상이 바뀌는 것을 하나도 놓치지 않으려고 귀를 기울이는 것처럼 보였고, 결국 신경쇠약에 걸려버린 사람 처럼 느껴졌기 때문이다.

회사를 옮기면서 면접을 보게 되었는데, 최종 면접관이 내게 물었다. 이직을 하면 무얼 하고 싶냐고. 망설임 없이 대답하기를
내가 지금까지 쌓은 대부분의 지식은 오픈소스에서 얻었습니다. 지금까지는 여유 자체가 없이 쫓기는 생활을 해 왔는데, 이젠 스스로를 돌아보고 정리한 후 내가 받은 지식과 그동안 내게 축적된 경험들을 잘 엮어 오픈소스 프로젝트에 참여함으로서 그동안의 이득을 돌려주고 싶습니다.
라고 했다.

그럭저럭 그 회사로 이직을 하게 되었고, 여유를 찾으려 했으나 안타깝게도 이직한 부서 자체가 매번 불이 나는 바람에 불끄느라 정신없이 8개월여가 지나갔다.
하지만 그 동안에도 조금씩이나마 Neurasthenia 에 대한 구상과 설계, 코드를 만들어갔다.
이제 해가 바뀌기 전에 지금까지의 결과물을 세상에 내 놓는다.
지금까지 구현된 내용을 짧게 정리하면 다음과 같다.
  1. Servlet container 의 기능을 한다. 고로 servlet, jsp 를 만들어 동작시킬 수 있다.
  2. Comet server 역할을 한다. 브라우저상에서 채팅이 가능하다.
  3. 프로토콜에 독립적인 네트워크 서버 역할을 한다. 기본적으로 HTTP 와 STOMP 프로토콜을 지원한다.
늙은이 소리를 덧붙이자면, 소시적엔 이런 소스를 오픈하다니 참으로 대단하다 란 생각을 달고 살았다. 그리고 난 대체 언제쯤 이런 걸 해 볼수 있을까를 고민했었다.
몇번 이런 저런 프로젝트를 해 볼까 생각할 때 마다 어느정도 모양이 잡히기도 전에 내게 부족한 점이 튀어나와서 이 부분을 보완하고 다시 시작하자란 생각에 에둘러 추진할 생각을 접곤 했다.
어떻게 보면 neurasthenia 도 이런 저런 부족한 점이 무척 많다. 하지만 언제까지나 시작하지않는다면 결코 완성하지 못할것이기에 부끄러움을 무릅쓰고 세상에 내놓기로 했다.

자 주사위는 이미 내 손을 떠났고 이제 이 배가 신대륙을 발견할지, 망망대해를 영원히 떠도는 플라잉 더치맨이 될지 아니면 또다시 세이브조차 하지 않고 지워버릴지는 앞으로 내가 어떻게 neurasthenia 를 운영할지에 달렸다.

참고로 neurasthenia 를 사용한 채팅 서버가 돌고 있다.

Posted by eoh

2010/01/02 03:06 2010/01/02 03:06
, , ,
Response
No Trackback , No Comment
RSS :
http://endofhope.com/tc/rss/response/18

콩의 전설

사내 라이브러리를 쓸 일이 있어 문서를 보다 main class 가 아닌 것은 모두 빈즈 란 이름을 붙인 것을 보았다.

삽질계에 빈즈 란 용어가 쓰이기 시작한 것은 모델 1 (이라 쓰고 JSP 에 다 때려 박는다 라고 읽는다) 방식에서 웹에서의 MVC, 일명 모델 2 방식에 대해 갑론을박이 벌어지면서 라고 기억한다.
모델 2란 이름으로 봐선 일정한 방식을 특징지어 말하는 것 같지만, 실질적으로 JSP는 View 역할만으로 한정하고 Controller 와 Model 역할을 분리한 (혹은 분리할 수 있는 것처럼 보인) 수많은 방법론이 모델 2 라고 자칭했었다. 그중 당장 생각나는 것만 해도 커스텀 태그 라이브러리, 스트러츠, 웹 매크로, 티, 벨로서티 등등 그야말로 백가쟁명의 시대가 따로 없었다.
이렇게 딱히 이것이다 라고 정의된 것이 없다 보니 악화가 양화를 구축한다고 Beans 란 이름만 붙여서 클래스를 만들고 JSP 에서 호출하면 은근슬쩍 모델 2 입네 하는 것들도 있었고 사람들도 대충 뭉뚱그려 쳐 주는 현상이 있었다.

본디 JavaBeans 스펙은 캡슐화를 지키면서 introspection 을 하지 않고 외부 클래스가 내부 속성에 대한 접근자를 알아내기 위한 규약을 정의하고 있다. 이때만 하더라도 세상은 모두 component 들의 조합으로 이루어 질 줄 알았고 (혹은 기대했고) 이를 위해서는 component 에 대한 조합을 (손으로 할 수는 없으니) 할 Tool 이 component 의 속성에 접근하는 것이 필요했기 때문이었다.
하지만 세상사가 다 그렇듯 자바 데스크탑 컴포넌트는 글자 그대로 쫄딱 망했고 JavaBeans 스펙도 묻히는 가 싶더니 (약간 생뚱맞게도) 웹에서의 MVC 에서 데이터 구조를 표현하는데 부활하게 되었다 라고 쓰고 싶었는데 사실은 그렇지 않다.

첫 문장에서 썼듯 원래의 의도와는 전혀 상관없게도 데이터 표현 (getter/setter 를 쓴다) 에 비즈니스 로직까지도 얼렁뚱땅 덧붙여진 클래스면 대충 Beans 란 이름을 붙여 쓰는 경우가 허다하다. 솔직히 말하자 당최 Beans 란 postfix 를 왜 붙이는지 모르겠다.
까 놓고 보면 getter/setter 는 있되 JavaBeans 스펙에서 말하는 규약도 따르지 않는다면 굳이 이름에다 Beans 를 붙일 아무런 이유가 없다.
나는 이것이야말로 누가 어떤 의도로 시작한 지는 모르지만 대충 이렇게 해 왔으니 따라 한다는 관습에 지나지 않는다고 생각한다.

지금 자신의 class 에 Beans 라는 이름이 붙은 클래스들이 있다면 다른 것으로 이름을 바꾸어 보면 좋겠다. 예를 들면 A4Beans, B4Beans 가 있다면 A4Adzuki, B4Adzuki 로 바꾸어 놓고 보자 - Adzuki 는 팥이다.
결론적으로 아무런 차이가 없다면 그저 Beans 를 클래스를 구분하기 위한 postfix 로 사용한 것이며 만약 PrinterBeans 까지 있었다면 구분자의 효과도 없었을 것이다.

다시 말하자.
Beans 라는 이름을 쓰고 싶다면 최대한 (그 의도대로 쓰는 사람이 드물다 할지라도) 스펙에서 정의된 형식을 유지하는 것이 좋겠다.
비즈니스 로직과 뒤엉키는 것이 불가피하다면 그냥 Beans 라는 postfix 를 붙이지 말고 절약된 5자를 좀 더 친절한 클래스명으로 하는데 시간을 들이는 것이 정신 건강에 좋을 성싶다.

Posted by eoh

2009/12/30 23:15 2009/12/30 23:15
, , ,
Response
No Trackback , No Comment
RSS :
http://endofhope.com/tc/rss/response/17

Dynamic language 유감

예전 회사에서는 C 와 Java 가 사내 개발 언어였다.
근자에 들어 Dynamic 한 속성을 중시하는 script 언어들이 널리 회자되면서 Java 언어는 사용하기에 불편한 언어군에 속하는 것으로 여겨지지만, 예전에 C 로 개발하는 부서와 협업을 하다보면 Java 로 개발하는 것은 어느 정도 거저 먹는구나 란 느낌을 언제나 받았다.
전 직장에서는 수행시간에  critical 한 제품은 C로 개발하는 것이 당연시 되고 생산성과 유지 보수 및 향후 확장성이 더 중요한 제품은 Java 가 선택되었다.
나는 Java 를 사용하여 Middleware 를 만드는 부서에 속해 있었고, 나를 비롯한 구성원들의 화두는 Java 의 생산성과 확장성을 유지하면서도 C 만큼의 Performance 를 어떻게 하면 낼 수 있을까 였다.
그동안 Native thread 에 대한 지원, Garbage collector 의 성능 향상, Native io 지원, Hot spot VM 혹은 JIT compiler 등 Java 언어 및 가상머신은 그 성능에 있어 괄목할만한 발전을 이루어 냈고 우리는 이러한 발전을 오롯히 제품에 반영하려고 노력함으로써, 내심 이정도 Performance 를 내는 Middleware 를 확장성과 안정성 및 유지 보수의 용이성을 전혀 희생하지 않고서 C로 구현한다는 것은 어떠한 경우라도 수지타산이 맞지 않을 것이다란 생각을 가졌다.
그리고 해당 제품과 Java 로 만들어진 다른 Middleware 들이 Mission critical 한 영역에까지 저변을 넓히는 것을 목격하면서 우리의 생각이 틀리지 않았다는 확신을 가질 수 있었다.

예전 포스트에서도 언급한 바 있듯 지금은 Ruby 를 사용한 web application 을 개선하는 일을 하고 있다.
혹자는 Java 언어에 비해 생산성이 3배에서 10배까지 높다는 script 언어를 실무에서 사용할 기회를 얻은 것을 행운이라고 생각할지도 모르겠다.
일반적으로 Script 언어는 구닥다리? 컴파일 언어에 비해 생산성이 높다고 한다. 특히 Ruby 의 경우 여러 설문 결과 및 개인적인 경험담들을 쉽게 찾을 수 있다.
하지만 내가 이 글을 쓰는 이유는 과연 Ruby 의 생산성 신화는 과연 타당한 것인지 의문이 생겼기 때문이다.

지금 파악된 바로는 내가 소속된 부서에서 맡은 서비스는 일반적인 RDBMS 에 데이터를 저장하고 web page 를 서비스하는데 그치지 않고 SMS, MMS 문자 전송이나 OPEN API 지원까지 포함하다보니 코드의 라인 수가 10만 라인을 훌쩍 넘는다. 그리고 개발 인력의 수가 10여명 정도이다.

내가 느끼는 애로사항은 Ruby는 지나치게  Dynamic 하게 사용하기가 쉽다는 것이다.
예를 들어 코드 상에서 특정 메써드가 어디에 정의되어 있는지 알고 싶을 때 grep 이나 ack 로 이름 검색을 해야 한다는 건 좀 지나치지 않는가? 그렇게 대충 찾은 후엔 해당 위치를 일일이 파악하면서 과연 어느 정의가 내가 찾던 그 정의인지 확인해야 하는 작업을 해야 한다는 건 집중력을 흐트러뜨리는 데는 이것만한 것이 없었다.
이것만 해도 슬슬 어깨가 결려오는데 아무리 찾아도 안 찾기던 경우가 2가지 있었다. 하나는 클래스명과 메써드 명을 - 그것도 변수명에 넣어서 넘긴 후 introspection 을 사용하여 runtime 시에 동적으로 클래스 인스턴스를 생성한 후 메써드를 호출하는 경우였고 두번째는 method_missing 을 썼는데 parameter 로 넘긴 문자열의 prefix 가 무엇인가에 따라 prefix 를 뗀 나머지 문자열을 이름으로 가진 메써드를 호출하는 경우였다.
이러한 경우 여러 사람이 작업하다 보면 본의 아니게 이름공간이 훼손되는 경우가 생길 가능성이 짙다. Java 로 예를 들자면 Date 객체가 있는데 이게 대체 java.util.Date 인지 java.sql.Date 인지 모호한 경우가 되겠다.
Strictly typed 언어인 경우 compile 시에 이게 모호하다는 경고와 함께 발견 가능하다. IDE 를 쓰는 경우 ambiguity 여부를 바로 알려주기도 한다. 그런데 Ruby 에서 이런 일이 발생하면 이 에러가 동작시에나 검출된다. 이미 배포해서 서비스 하는 도중에 이런 일이 발생했다는 걸 알면 등에 식은 땀이 흐를 것이 뻔하고 미리 좀 알수 있었으면 얼마나 좋을까 란 생각이 절로 날 것이다.

물론 이러한 Dynamic 언어들을 옹호하는 측에선 작성자의 완전한 자유를 보장하는 것이 무엇보다 중요하기 때문에 의도적으로 그러한 가능성을 열어 둔 것이며, 이러한 오류는 테스트 케이스를 촘촘하게 준비함으로써 피할수 있다 라고 주장한다. 적절한 시간적인 여유가 있는 경우에는 그럴 수도 있겠다. 그런 여유를 가지고 구현하고 있는 곳을 알면 나에게도 좀 알려주었으면 한다.
테스트 케이스를 잘 잡으면 모든 오류를 방지할 수 있다 란 이야기가 어느 정도 먹혀들어가고 있다는 사실은 아직 Ruby 로 현실적인 상황에서 Mission critical 한 시스템은 구축된 적이 없다는 반증으로 밖엔 생각할 수 없다.

생산성의 정의를 협의로 생각한다면 한정된 시간에 얼마나 많은 기능을 구현할수 있는가에 대한 척도라고 할 수 있겠다. 이러한 점에서 3배, 10배 이야기도 나오는 것일 게다.
10사람이 할 일을 한 사람이 동일한 시간에 한다면 10배 이런 식일 것이다.
자 여기서 곰곰히 생각해 보자. 동일한 능력을 가진 사람이 사물을 보고 행동할 때 특정 패러다임을 다른 패러다임으로 바꾸었더니 10배 더 많은 Output을 내려면 어떻게 해야 할까?
내 생각에는 어느 한 패러다임이 굉장히 규격화된 경우라서 많은 기능을 생각없이 찍어낼 수 있으면 가능하다고 생각한다. 아마도 Active* 계열을 쓰는 Rails 프레임워크가 대표적인 경우일 것이다.
그런데 이건 좀 이상하지 않은가?
우리는 굉장히 자유로운 표현력을 가진다. 그런데 우리는 굉장히 높은 생산성도 가진다.
아무리 생각해도 이 두 문장은 미묘한 위화감을 준다.
아마도 두번째 문장 뒤에
- 단 우리가 미리 결정한 방식을 따르는 경우에는
이런 구절이 덧붙으면 적절할 것 같다.

생산성은 위에서 말하는 협의의 뜻으로 생각할 것이 아니라 향후 유지 및 보수의 유이성까지 포함한 광의로 사용되어야 한다. 그리고 설정보다 관례란 이야기에서 상당히 심한 강제의 냄새를 맡는다면 내가 지나치게 성마른 것일까?
표현력을 추구하자면 파악이 어려워져 유지보수가 어려워지고 (협의의) 생산성을 극대화 하자면 정해진 관례를 따라야만 한다.

Ruby 의 생산성에 대한 올바른 평가는
  1. Mission critical 한 부분에서
  2. 상당히 많은 수의 사람이 협업하며
  3. 복잡하고 많은 기능을 구현하는
3가지 조건을 만족하는 프로젝트의 결과를 본 후에야 납득할 만한 결론이 나올 것 같다.

Posted by eoh

2009/10/31 04:44 2009/10/31 04:44
, , , ,
Response
No Trackback , No Comment
RSS :
http://endofhope.com/tc/rss/response/10

10만 펙토리얼

자주 방문하는 프로그래밍 관련 포럼에 글이 하나 올라온 적이 있다.
10만 펙토리얼 계산 속도
윈도우 계산기로 계산 결과를 올려 놓는 사람부터 함수형 언어로 계산해 본 결과까지 하나의 목적을 위해 서로 다른 접근을 볼 수 있어서 즐거운 글이었다.
나도 당연히? 프로그램을 짜서 돌려 보았는데, 해당 글타래엔 올리지 않았다.
java 로 뭔가 하면 뻑하면 flame 이 생기는 걸 보았던 터라 간만에 생긴 흥을 내가 나서서 깨어버리곤 싶지 않아서였다.

어제 메일이 왔는데, 서버 계정 만료일이 다가왔다고 알려주는 메일이었다.
뭐 몇푼 되진 않지만, 그렇다고 이용하지 않는 계정을 놀릴 필요도 없고 해서 블로그를 써야할 마음이 들었다.

첨부한 코드는 Java 로 10만 펙토리얼을 구하는 코드이다.
argument 없이 돌리면 thread 를 4개 생성하여 부분곱을 구하고 나중에 해당 부분곱들의 결과를 합하여 최종 값을 구해 낸다.
이 코드를 테스트할때 4개짜리 프로세서를 가진 기계에서 돌렸기 때문에 쓰레드를 3~4개가 가장 성능이 좋을 줄 알았는데, 쓰레드 숫자가 16개 까진 상당히 좋은 결과가 나와서 의외? 였다.
결과는
4개 이상이면 context switching 비용이 분명 들 텐데, 분명 인생의 오묘함도 이런 게 아닐까?

Posted by eoh

2009/08/31 21:40 2009/08/31 21:40
, ,
Response
No Trackback , No Comment
RSS :
http://endofhope.com/tc/rss/response/3


블로그 이미지

말할 수 있는 것은 분명하게 말해질 수 있다. 말해질 수 없는 것에 대해서는 침묵해야 한다. 논리 철학 논고 - 루드비히 비트겐슈타인.

- eoh

Archives

Authors

  1. eoh

Recent Comments

Recent Trackbacks

Calendar

«   2012/05   »
    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    

Site Stats

Total hits:
20059
Today:
44
Yesterday:
47