성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <h1 style='font-family: Malgun Gothic, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>C# - 간단한 HyperLogLog 자료 구조 테스트</h1> <p> 재미있는 글이 하나 소개되었습니다. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 확률적 자료구조를 이용한 추정 - 유일한 원소 개수(Cardinality) 추정과 HyperLogLog ; <a target='tab' href='https://d2.naver.com/helloworld/711301'>https://d2.naver.com/helloworld/711301</a> </pre> <br /> 위의 글에 나온대로 "HyperLogLog는 매우 적은 메모리로 집합의 원소 개수를 추정할 수 있는 방법"입니다. 물론, 적은 메모리라는 장점을 위해 "정확성"을 희생하는 식인데요. 사실, '정확성'이 그다지 중요하지 않을때가 생각보다 많기 때문에 응용할 곳은 제법 많습니다.<br /> <br /> 예를 들어, 구글의 검색어에 대한 예상 결과 수를 보여주는 기능이 바로 그러한 사례 중의 하나입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > http://www.google.com/webhp?complete=1&hl=en 검색에 관해서 ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/96'>http://www.sysnet.pe.kr/2/0/96</a> </pre> <br /> "ebay" 검색어를 포함한 웹 페이지 수가 10,000개로 대략 나오든지, 아니면 11,382개라고 정확하게 나오든지 사용자에게 크게 영향을 주는 것은 아닙니다. 하지만, 구현하는 입장에서 볼 때 그걸 정확하게 구하기 위해서는 적지 않은 오버헤드가 수반될 수 있습니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 이론적인 설명은 "<a target='tab' href='https://d2.naver.com/helloworld/711301'>확률적 자료구조를 이용한 추정 - 유일한 원소 개수(Cardinality) 추정과 HyperLogLog</a>" 글에서 너무나 잘해주고 있으므로 여기서는 C#으로 간단하게 실습하는 것을 소개하겠습니다.<br /> <br /> 일단, 검색해 보면 이미 ^^ C# 구현체가 있으니 이걸 사용하겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > HyperLogLog C# implementation ; <a target='tab' href='http://adnan-korkmaz.blogspot.kr/2012/06/hyperloglog-c-implementation.html'>http://adnan-korkmaz.blogspot.kr/2012/06/hyperloglog-c-implementation.html</a> </pre> <br /> 또한, 유일한 단어 수를 계산하는 것 대신 전체가 유일 항목임을 보증하는 임의의 GUID 수를 생성해서 테스트 해보았습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > <span style='color: blue; font-weight: bold'>HyperLogLog log = new HyperLogLog(0.01); HashSet<string> dict = new HashSet<string>(); </span> for (int i = 0; i < 100; i++) { string txt = Guid.NewGuid().ToString(); <span style='color: blue; font-weight: bold'>log.Add(txt);</span> bool result = dict.Contains(txt); if (result == false) { <span style='color: blue; font-weight: bold'>dict.Add(txt);</span> } } Console.WriteLine("CountFromHash: " + dict.Count()); Console.WriteLine("CountFromHyperLogLog: " + log.Count()); // 출력결과 CountFromHash: 100 CountFromHyperLogLog: 100 </pre> <br /> 일단, 100개로 시작했을 때 HashSet으로 하든 HyperLogLog로 하든 계산된 수는 100으로 동일했습니다. 단지, 가끔 특정 GUID 조합에서는 Hash 코드가 치우치는 탓인지 HyperLogLog의 경우 98~99를 출력하기도 합니다.<br /> <br /> 수를 늘리면 점차로 차이가 뚜렷해지기 시작합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ==== 10,000개인 경우 ==== CountFromHash: 10000 CountFromHyperLogLog: 9976 ==== 100,000개인 경우 ==== CountFromHash: 100000 CountFromHyperLogLog: 100638 </pre> <br /> 100000000까지 늘리면 이제 <a target='tab' href='http://www.sysnet.pe.kr/2/0/946'>(x64에서조차도) HashSet으로는 Out of memory</a>로 인해 더 이상 테스트가 되지 않습니다. 반면 HyperLogLog에서는 놀라운 메모리 사용량을 보여줍니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > ==== 100,000,000개인 경우 ==== CountFromHash: OOM 발생 CountFromHyperLogLog: 101648822 (메모리 사용량: 4.8MB) </pre> <br /> 게다가 오차도 0.01%수준으로 괜찮은 정확도를 보여줍니다.<br /> <br /> 한 가지 재미있는 것이 있다면, HyperLogLog.Add 메서드에 전달된 object 인자를 별도의 getHashCode 메서드를 이용해 구한다는 것입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public static uint getHashCode(string text) { uint hash = 0; for (int i = 0, l = text.Length; i < l; i++) { hash += (uint)text[i]; hash += hash << 10; hash ^= hash >> 6; } hash += hash << 3; hash ^= hash >> 6; hash += hash << 16; return hash; } </pre> <br /> 이것을 .NET Framework의 Object.GetHashCode()로 치환해도 결과가 거의 비슷했습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > public static uint getHashCode(string text) { return (uint)text.GetHashCode(); } </pre> <br /> 참고로, Hash 코드를 구하는 것에는 정답이 없습니다. 아래의 글에서도 이야기했었지만,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; background-color: #fbedbb; overflow: auto; font-family: Consolas, Verdana;' > 괜찮은 문자열 해시 함수? ; <a target='tab' href='http://www.sysnet.pe.kr/2/0/1222'>http://www.sysnet.pe.kr/2/0/1222</a> </pre> <br /> <div style='BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: Malgun Gothic, Consolas, Verdana; COLOR: #005555'> 해시 함수는, 결국 해당 '업무 도메인'에서 사용되는 문자열 셋이 다르기 때문에 (가능하다면) 그에 따른 적절한 테스트를 해보고 선택하시는 것이 좋습니다.<br /> </div><br /> <br /> (<a target='tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?fid=840&boardid=331301885'>첨부 파일은 이 글의 테스트 코드를 포함</a>하고 있습니다.)<br /> </p><br /> <br /> <br /><hr /><span style='color: Maroon'>[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
8415
(왼쪽의 숫자를 입력해야 합니다.)