똑같은 실수의 반복

의도한 대로 동작하지 않는 프로그램 때문에 토/일 집에서 계속 모티어만 뚫어지게 쳐바 보았습니다.
모두 패떳을 모면서 키득대고 있는데 지난주에 포스팅한 글이 갑자기 떠올랐습니다.

http://www.jaso.co.kr/303

Reduce에서 매번 새로운 객체를 생성하지 않고 하나 만들어서 재사용한다는 글이 있었는데 문제의 원인은 여기에 있었습니다.
map에서 여러개의 값을 넘겨주고자 별도의 사용자 정의 클래스를 하나 만들었습니다.

public class MyVO implements Writable {
  HashSet<String> objects = new HashSet<String>();
 
  public MyVO() {
  }

  public MyVO(HashSet<String> objects) {
    this.objects = objects;
  }
 
  @Override
  public void readFields(DataInput in) throws IOException {
    int size = in.readInt();
   
    for(int i = 0; i < size; i++) {
      objects.add(WritableUtils.readString(in));
    }
  }
 
  @Override
  public void write(DataOutput out) throws IOException {
    out.writeInt(objects.size());
    for(String eachObject: objects) {
      WritableUtils.writeString(out, eachObject);
    }
  }
}   

Hadoop이 Reduce task를 실행시키면 reduce task는 map에서 전달된 값을 sort 하면서 reduce() 을 호출합니다. 이때 전달되는 값을 다음과 같은 로직으로 만들어서 전달합니다.(Hadoop의 WritableSerialization 클래스 중)
    public Writable deserialize(Writable w) throws IOException {
      Writable writable;
      if (w == null) {
        writable
          = (Writable) ReflectionUtils.newInstance(writableClass, getConf());
      } else {
        writable = w;
      }
      writable.readFields(dataIn);
      return writable;
    }

이 코드에 보면 기존 value 가 null인 경우에는(w == null) 새로운 객체를 만들고 그렇지 않느면 기존 객체에 readFields()를 바로 호출해서 사용합니다. 이런 상황에서 위의 MyVO의 readFileds() 메소드의 구현을 보면 objects.add()가 호출됩니다.
deserialize()가 호출될 때 마다 값이 계속 증가하게 되어 예상하지 않은 값이 objects에 계속 add 되게 됩니다. 따라서 MyVO의 readFields 부분을 다음과 같이 수정해야 합니다.
  @Override
  public void readFields(DataInput in) throws IOException {
    int size = in.readInt();
    objects.clear();
    for(int i = 0; i < size; i++) {
      objects.add(WritableUtils.readString(in));
    }
  }

요즘 삽질을 너무 많이 하고 있다는 생각이 드네요... 슬럼픈가?

크리에이티브 커먼즈 라이센스
Creative Commons License

Posted by 김형준


Trackback URL : http://www.jaso.co.kr/trackback/308

Comments List

  1. gruter 2008/11/10 15:55 # M/D Reply Permalink

    왜 이런걸 실수할까 ㅋㅋㅋ

  2. k 2008/11/12 11:49 # M/D Reply Permalink

    예전에 저도 그거때문에 당한 적이 있어요. 객체를 모아놓고 나중에 보니 전부 같은 값이 들어있어서.. 처음엔 버그인줄 알았는데 메모리 아끼는 feature라서 당황.

    객체 재사용은 코드로는 오래전부터 되어 있었는데, 문서화는 0.17.x인가 꽤 늦게 된 편이에요. hadoop이 문서화가 좀 엉망이라.. 옛날 버전 기반으로 작업한다고 해도 문제가 생긴다면 최신 문서를 참고해보는 것도 좋을 거에요.

  3. typos 2009/06/11 16:02 # M/D Reply Permalink

    또 당했음 ㅋㅋㅋ.

    1. 김형준 2009/06/11 16:41 # M/D Permalink

      ㅋㅋㅋ 눈뜨고도 당하는...

Leave a comment
« Previous : 1 : ... 128 : 129 : 130 : 131 : 132 : 133 : 134 : 135 : 136 : ... 388 : Next »