제 인생에서 두 줄 트리를 쓴 게 몇 번째예요.
                                            
                                                
                                                
                                                
                                                
                                                
                                                 8468 단어  Go
                    
개요 
사람들은 인생에서 트리를 몇 번 쓴다고 한다. 그래서 몇 번째 트리에서 슈다치의 다츠-클론을 복제해 보았다. 트리의 기사가 많아서 여기서 Go에 이식해서 발견한 것들을 몇 가지 공유하고 싶다.
이번 결과: https://github.com/ikawaha/dartsclone
darts-clone 
원소재는 이쪽.Java 버전과 Python 버전이 있습니다.
원소재는 이쪽.Java 버전과 Python 버전이 있습니다.
아무튼 해보겠습니다. 
작업 원리와 구조를 고려하지 않고 복제를 시도했다. 이후 GO처럼 재구성했다. 자바 버전과 Python 버전의 코드를 왜 Go에 떨어뜨렸는지 흥미롭다.
재구성 
사실 Darts-clone의 Go 버전이 이미 있습니다. 제작 후에야 알아차렸습니다.
https://github.com/euclidr/darts
이것은 마치 본가의 C++ 버전의 clone인 것 같아서 이것과 비교하였다.
벤치에서 찾아봤는데byte수조에서 쌍수조를 처리할 때와 unit32수조에서 쌍수조를 처리할 때 같은 처리를 하기 위해 두 가지 측면에서 함수를 정리했습니다.이 함수의 호출이 느려서 그런 것 같습니다. 이것을 여러 상황에서 가득 쓴 함수로 바꾸어 호출을 줄이면 속도가 대체적으로 같습니다.
변경 전:func (a MmapedDoubleArray) ExactMatchSearch(key string) (id, size int, err error) {
    return exactMatchSearch(a, key) // ← 共通処理でまとめてた
}
변경 후: 손으로 변경func (a MmapedDoubleArray) ExactMatchSearch(key string) (id, size int, err error) {
    nodePos := uint32(0)
    unit, err := a.at(nodePos)
    if err != nil {
        return -1, -1, err
    }
    for i := 0; i < len(key); i++ {
        nodePos ^= unit.offset() ^ uint32(key[i])
        unit, err = a.at(nodePos)
        if err != nil {
            return -1, -1, err
        }
        if unit.label() != key[i] {
            return -1, 0, nil
        }
    }
    if !unit.hasLeaf() {
        return -1, 0, nil
    }
    unit, err = a.at(nodePos ^ unit.offset())
    if err != nil {
        return -1, -1, err
    }
    return int(unit.value()), len(key), nil
}
 
 
이렇게 하면 비교 프로그램과 같은 성능을 가지지만, 비교 프로그램은 배열된 색인 검사 등 잘못된 검사를 생략하기 때문에 좀 빠르다. 하지만,오차 범위이기 때문에 오류 검사를 넣기로 했습니다. 패닉에서 멈추는 것은 미묘합니다.
mmap 지원 
sudachi는 mmap에서 사전을 공유하고 메모리를 절약하는 데 사용할 수 있습니다. 따라서 sudachi에서 사용하는 darts-clone은 mmap를 지원합니다. GO에서도 mmap를 지원합니다. linux계와 윈도우즈의 대응이 바뀌기 때문에 테스트 등이 좀 번거롭습니다.darts-clone의 쌍수조 자체는byte열이기 때문에 솔직하게 대응하면 됩니다.
하지만 아무리 mmap로 읽을 때의 속도(1/10 정도)도 없다.
mmap를 사용하지 않는 상황에서 uint32의 배열로 두 배열을 나타냅니다. mmap를 사용할 때 이것은 작은 단자 순서의byte 배열입니다. 여기서 unit32의 값을 꺼냅니다.
처음에 쓴 코드는 Reader를 사용하여 위치를 지정한 후 Read() 읽은 것입니다.    var ret uint32
    if err := binary.Read(r, binary.LittleEndian, &ret); err != nil {
        return 0, fmt.Errorf("read error, %v", err)
    }
이 부분은 느린 것 같습니다. 이 배열을 직접 지정하고,    if int(i+1)*unitSize > len(a.raw) {
        return 0, fmt.Errorf("index out of bounds")
    }
    ret := binary.LittleEndian.Uint32(a.raw[i*unitSize : (i+1)*unitSize])
읽은 후, mmap 버전도 동등한 성능을 나타냈다.
그나저나 binary.LittleEndian.Uint32()의 내용은,func (littleEndian) Uint32(b []byte) uint32 {
    _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
    return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
그렇군요. 간단합니다.
아, 그리고 syscall은 deprecated, golang입니다.org/x/sys 사용.
총결산 
수다치에 해당하는darts-clonegithub.com/ikawaha/darts-clone을 발표했습니다. 이렇게 하면 사전을 찾는 기초 위에서 준비가 될 수 있기 때문에botchbotch와sudachi를 이식하고 싶습니다.
그나저나 작년부터 개발을 가로막았던 그거랑 이거랑 다 S로 갔는데 거기서 못 하는 벽에 부딪혀서 빼야 할 것 같지 않나. 이게 없으면 개발할 것 같은 느낌도 든다(^^`灬.
지난해부터 개발을 가로막고 있는 이것저것 →   Happy hacking!
                
                    
        
    
    
    
    
    
                
                
                
                
                    
                        
                            
                            
                            Reference
                            
                            이 문제에 관하여(제 인생에서 두 줄 트리를 쓴 게 몇 번째예요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
                                
                                https://qiita.com/ikawaha/items/edb4e18960ae6e4babc3
                            
                            
                            
                                텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                            
                            
                                
                                
                                 우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                            
                            
                        
                    
                
                
                
            
사실 Darts-clone의 Go 버전이 이미 있습니다. 제작 후에야 알아차렸습니다.
https://github.com/euclidr/darts
이것은 마치 본가의 C++ 버전의 clone인 것 같아서 이것과 비교하였다.
벤치에서 찾아봤는데byte수조에서 쌍수조를 처리할 때와 unit32수조에서 쌍수조를 처리할 때 같은 처리를 하기 위해 두 가지 측면에서 함수를 정리했습니다.이 함수의 호출이 느려서 그런 것 같습니다. 이것을 여러 상황에서 가득 쓴 함수로 바꾸어 호출을 줄이면 속도가 대체적으로 같습니다.
변경 전:
func (a MmapedDoubleArray) ExactMatchSearch(key string) (id, size int, err error) {
    return exactMatchSearch(a, key) // ← 共通処理でまとめてた
}
func (a MmapedDoubleArray) ExactMatchSearch(key string) (id, size int, err error) {
    nodePos := uint32(0)
    unit, err := a.at(nodePos)
    if err != nil {
        return -1, -1, err
    }
    for i := 0; i < len(key); i++ {
        nodePos ^= unit.offset() ^ uint32(key[i])
        unit, err = a.at(nodePos)
        if err != nil {
            return -1, -1, err
        }
        if unit.label() != key[i] {
            return -1, 0, nil
        }
    }
    if !unit.hasLeaf() {
        return -1, 0, nil
    }
    unit, err = a.at(nodePos ^ unit.offset())
    if err != nil {
        return -1, -1, err
    }
    return int(unit.value()), len(key), nil
}
 
 이렇게 하면 비교 프로그램과 같은 성능을 가지지만, 비교 프로그램은 배열된 색인 검사 등 잘못된 검사를 생략하기 때문에 좀 빠르다. 하지만,오차 범위이기 때문에 오류 검사를 넣기로 했습니다. 패닉에서 멈추는 것은 미묘합니다.
mmap 지원 
sudachi는 mmap에서 사전을 공유하고 메모리를 절약하는 데 사용할 수 있습니다. 따라서 sudachi에서 사용하는 darts-clone은 mmap를 지원합니다. GO에서도 mmap를 지원합니다. linux계와 윈도우즈의 대응이 바뀌기 때문에 테스트 등이 좀 번거롭습니다.darts-clone의 쌍수조 자체는byte열이기 때문에 솔직하게 대응하면 됩니다.
하지만 아무리 mmap로 읽을 때의 속도(1/10 정도)도 없다.
mmap를 사용하지 않는 상황에서 uint32의 배열로 두 배열을 나타냅니다. mmap를 사용할 때 이것은 작은 단자 순서의byte 배열입니다. 여기서 unit32의 값을 꺼냅니다.
처음에 쓴 코드는 Reader를 사용하여 위치를 지정한 후 Read() 읽은 것입니다.    var ret uint32
    if err := binary.Read(r, binary.LittleEndian, &ret); err != nil {
        return 0, fmt.Errorf("read error, %v", err)
    }
이 부분은 느린 것 같습니다. 이 배열을 직접 지정하고,    if int(i+1)*unitSize > len(a.raw) {
        return 0, fmt.Errorf("index out of bounds")
    }
    ret := binary.LittleEndian.Uint32(a.raw[i*unitSize : (i+1)*unitSize])
읽은 후, mmap 버전도 동등한 성능을 나타냈다.
그나저나 binary.LittleEndian.Uint32()의 내용은,func (littleEndian) Uint32(b []byte) uint32 {
    _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
    return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
그렇군요. 간단합니다.
아, 그리고 syscall은 deprecated, golang입니다.org/x/sys 사용.
총결산 
수다치에 해당하는darts-clonegithub.com/ikawaha/darts-clone을 발표했습니다. 이렇게 하면 사전을 찾는 기초 위에서 준비가 될 수 있기 때문에botchbotch와sudachi를 이식하고 싶습니다.
그나저나 작년부터 개발을 가로막았던 그거랑 이거랑 다 S로 갔는데 거기서 못 하는 벽에 부딪혀서 빼야 할 것 같지 않나. 이게 없으면 개발할 것 같은 느낌도 든다(^^`灬.
지난해부터 개발을 가로막고 있는 이것저것 →   Happy hacking!
                
                    
        
    
    
    
    
    
                
                
                
                
                    
                        
                            
                            
                            Reference
                            
                            이 문제에 관하여(제 인생에서 두 줄 트리를 쓴 게 몇 번째예요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
                                
                                https://qiita.com/ikawaha/items/edb4e18960ae6e4babc3
                            
                            
                            
                                텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                            
                            
                                
                                
                                 우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)
                            
                            
                        
                    
                
                
                
            
    var ret uint32
    if err := binary.Read(r, binary.LittleEndian, &ret); err != nil {
        return 0, fmt.Errorf("read error, %v", err)
    }
    if int(i+1)*unitSize > len(a.raw) {
        return 0, fmt.Errorf("index out of bounds")
    }
    ret := binary.LittleEndian.Uint32(a.raw[i*unitSize : (i+1)*unitSize])
func (littleEndian) Uint32(b []byte) uint32 {
    _ = b[3] // bounds check hint to compiler; see golang.org/issue/14808
    return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24
}
수다치에 해당하는darts-clonegithub.com/ikawaha/darts-clone을 발표했습니다. 이렇게 하면 사전을 찾는 기초 위에서 준비가 될 수 있기 때문에botchbotch와sudachi를 이식하고 싶습니다.
그나저나 작년부터 개발을 가로막았던 그거랑 이거랑 다 S로 갔는데 거기서 못 하는 벽에 부딪혀서 빼야 할 것 같지 않나. 이게 없으면 개발할 것 같은 느낌도 든다(^^`灬.
지난해부터 개발을 가로막고 있는 이것저것 → Happy hacking!
Reference
이 문제에 관하여(제 인생에서 두 줄 트리를 쓴 게 몇 번째예요.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/ikawaha/items/edb4e18960ae6e4babc3텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)