2009-03-02 4 views
5

거대한 트리 오브 트리 (7,000)를 디스크에 직렬화해야합니다. 원래 우리는이 나무를 Kodo와 데이터베이스에 보관했지만,이 트리를 메모리에로드하려면 수천 개의 쿼리를 수천 번 만들 것이고, 지역 우주 사용 ​​가능 시간의 좋은 부분을 차지할 것입니다. Java 객체 직렬화 성능 팁

나는 이것에 대한 직렬화를 시도하고 실제로 나는 성능 향상을 얻을. 그러나 필자는 자신의 맞춤 직렬화 코드를 작성하여이를 향상시킬 수 있다고 생각합니다. 가능한 빨리이 직렬화 된 객체를로드해야합니다. 내 컴퓨터에서

는, 직렬화/이러한 개체를 직렬화 복원은 약 15 초 정도 걸립니다. 데이터베이스에서로드 할 때 약 40 초가 걸립니다. 나는 객체 트리에 있기 때문에, 그들은 서로를 참조하는 것을 고려,이 성능을 개선하기 위해 무엇을 할 수에

모든 팁?

답변

6

한 최적화는 클래스 기술자를 사용자 정의합니다. 이렇게하면 직렬화 된 데이터에 필요한 공간이 줄어 듭니다. 예를 들어 한 프로젝트에서 SerialUtil 클래스와 ClassesTable 클래스를 사용하는 방법을 참조하십시오.

만들기 클래스는 일부 성능상의 이점을 제공 할 수 있습니다 대신 직렬화의 외부화. 단점은 많은 수작업이 필요하다는 것입니다.

그럼 자바의 기본 직렬화보다 더 나은 성능을 제공 할 수 있습니다 예를 jserial을 위해, 다른 직렬화 라이브러리가 있습니다.또한 객체 그래프에 사이클이 포함되어 있지 않으면 직렬화 기가 표시된 객체를 추적 할 필요가 없기 때문에 조금 더 빨리 직렬화 할 수 있습니다 (jserial's FAQ의 "작동 방식"참조).

+1

나는 Externalizable 경로를 과거에 해왔고 대형 객체 그래프의 직렬화/비 직렬화에서 약 20-23 %의 성능 향상을 얻었다. 이 작업에 필요한 작업량은 사용자 정의해야하는 객체의 수에 비례합니다. – Robin

+0

http://code.google.com/p/fast-serialization/에서 체크 아웃하십시오. 문제 해결 :-) –

1

스트림 (GZIPOutputStream)을 압축 해 보았습니까?

+0

로딩 및 저장시 성능이 향상되어야하지만 질문에서 지정하지 않았고 실제로 공간도 "성능"측정 값입니다. –

+0

공간이 적 으면 디스크 액세스가 적어 지므로 직렬화 프로세스가 디스크 바인딩 인 경우에만 –

+0

이 줄어 듭니다.그것은 내 시스템에있는 것 같지 않습니다. 그것은 cpu 바인딩 된 것으로 보이므로 압축을하면 더 느려질 것입니다. –

1

이 내가 각 개체, 그것을 내 머리 위로 각각 개별적으로

  • 할당을 반대

    직렬화

    1. 직렬화를 형성하는 것이 어떻게 고유 키
    2. 객체가 보유 다른 객체에 대한 참조는 해당 객체의 고유 키를 직렬화의 객체 위치에 놓습니다.
    3. 저장 임의의 객체를 고유 키

    Unserialization

    1. 시작을 형성 사용하여 파일/데이터베이스/보관에 각 개체 (일반적으로 루트 (나는 바이너리로 변환 된 UUID를 사용합니다) 내가 용의자) 그것을 직렬화 해제하고 고유 한 키를 인덱스로 사용하여 그것을 리턴하십시오.
    2. 순차 화 스트림의 오브젝트 키를 사용하면 이 먼저 비 직렬화되었는지 확인하십시오. 지도 및 if 그것은 필요할 때 올바른 객체를로드하기위한 후크가있는 실제 객체 대신 게이지 로딩 프록시 (해당 객체에 대해이 두 단계를 반복하는)를 넣지 않으면 거기에서 가져옵니다. 하지만 그 정도 -

    편집, 당신은 그것을 조금 일을 복잡하게, 당신이 거기에 순환 참조가있는 경우 두 단계 직렬화 및 unserialization을 사용해야 할 수도 있습니다. 다른 데이터베이스에 클래스 기술자를 저장하고 개체 만 ID에 의해 그들에게 참조 스트리밍 할 수 있도록

  • +0

    그럴 수도 있겠지만, 꽤 많은 코드를 다시 작성해야 할 것입니다. –

    +0

    표준 직렬화보다 어떻게 개선 될까요? 내가 아는 한 기본 메커니즘에 의해 이미 완료되었습니다. –

    +0

    @saua 필요한 경우 각 객체를 한 번에로드하지 않고 지연로드하고 인스턴스화 할 수 있기 때문에 직접 바이트 수준으로 이동하여 직렬화 형식을 최적화 할 수 있습니다. – thr

    0

    성능면에서 나는 java.io 직렬화를 전혀 사용하지 말 것을 제안합니다. 대신 자신에게 바이트 내려.

    만약 당신이 트리를 java.io에 직렬화한다면 재귀가 너무 깊어지지 않도록 평평하게 (TreeSet처럼) 또는 가장 깊은 노드를 먼저 직렬화하도록 배열해야합니다. 중첩 된 readObject 호출이 아닌 역 참조를 가짐).

    코도에서 나무 하나를 읽는 방법이 없으면 놀랄 것입니다.

    +0

    Kodo에서이 작업을 수행하는 방법이 있지만 문제는 데이터베이스에서 개체를 만드는 방법에 따라 달라진다는 것입니다. 불행히도 데이터베이스는 우리가 할 수없는 방식으로 이루어져 있습니다. (모델을 변경할 방법이 없습니다) –

    10

    직렬화 할 필요가없는 인스턴스 변수에 '일시적'키워드를 사용하는 것을 잊지 마십시오. 불필요한 데이터를 더 이상 읽고 쓰지 않기 때문에 성능이 향상됩니다.

    +0

    어떤 경우에도 이는 일반적으로 중요한 고려 사항입니다. 나는 이미 이것을하고 있지만 그것을 언급하는 것이 중요합니다. +1 –

    4

    writeObject()readObject() 메소드를 구현하는 것이 좋습니다. 이렇게하면 트리의 각 노드에 대해 writting chidren 노드를 제거 할 수 있습니다. 기본 직렬화를 사용하면 각 노드는 모든 자식 노드와 직렬화됩니다.

    예를 들어

    , 의 writeObject() 트리의 모든 노드를 반복 만 트리 레벨을 식별 할 수 있도록 일부 마커 (노드 자체를하지 않고) 노드에 데이터를 기록해야 트리 클래스의.

    LinkedList에서이 메소드가 구현 된 방법을 확인할 수 있습니다. 각 단일 항목에 대해 이전 및 다음 항목을 기록하지 못하도록 동일한 접근 방식을 사용합니다.

    4

    고유 한 직렬화 코드를 작성하지 않으려면 Google Protocol Buffers을 시도하십시오. 자신의 사이트에 따르면

    프로토콜 버퍼는 구조화 된 데이터를 직렬화하는 구글의 언어 중립적 인 플랫폼 중립적 인 확장 메커니즘 - XML을 생각하지만, 빠르고, 작고, 간단. 데이터를 한 번 구성하는 방법을 정의한 다음 특수 생성 된 소스 코드를 사용하여 다양한 데이터 스트림 (Java, C++ 또는 Python

    )을 사용하여 구조화 된 데이터를 쉽게 읽고 쓸 수 있습니다.

    나는 그것을 사용하지 않았지만 그것에 대해 많은 긍정적 인 것들을 들었다. 게다가, 나는 커스텀 직렬화 코드를 유지해야만한다. 버그를 추적하는 것은 절대적으로 악몽 일 수있다. 그래서 누군가 다른 사람에게 당신을 위해 그것을시키는 것은 항상 좋은 일이다.

    0

    또한 XStream의 개체를 XML로 직렬화하고 다시 라이브러리하는 라이브러리를 살펴보십시오.

    +0

    나는 이미 이런 유형의 물체에 대해 Kodo보다 더 나빴다. Java 직렬화는 XStream보다 훨씬 빠릅니다. –

    0

    Colfer을 사용하여 bean을 생성 할 수 있으며 Java의 표준 직렬화 성능은 10 - 1000x boost를 얻습니다. 크기가 GB 이상이되지 않는 한 1 초도 채 안됩니다.