2016-11-03 2 views
2

NIC에서 패킷을 캡처하고 패킷 페이로드의 일부를 문자열로 저장하려고합니다.연도가 프로그래밍 방식으로 변경되었는지 확인하는 가장 효율적인 방법은 무엇입니까

저장해야하는 패킷의 일부는 SysLog로 알려진 로그 시간입니다. 각 패킷에는 다음과 같은 형식의 SysLog가 있습니다.

Nov 01 03 14:50:25 TCP...[other parts of packet Payload] 

위에서 볼 수 있듯이 SysLog 패킷에는 연도 번호가 없습니다. 내 프로그램이 일 년 내내 실행되어야하므로 패킷 SysLog에 연도 번호를 추가하고 SysLog를 기원 시간으로 변환해야합니다. 내가 저장해야하는 최종 문자열은 다음과 같다 : 나는 EpochTime에 시스템 로그를 변환하는 다음 코드 평화를 사용

1478175389-TCP, …. 

.

tm* tm_date = new tm(); 
Std ::string time = Current_Year; 
time += " "; 
time += packet.substr(0,18); 
strptime(time.c_str(), "%Y %b %d %T", tm_date); 
EpochTime = timegm(tm_date); 

currentYear 방법

는 :

std::string currentYear() { 
    std::stringstream now; 
    auto tp = std::chrono::system_clock::now(); 
    auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()); 
    size_t modulo = ms.count() % 1000; 
    time_t seconds = std::chrono::duration_cast<std::chrono::seconds>(ms).count(); 
#if HAS_STD_PUT_TIME 
#else 
    char buffer[25]; // holds "2013-12-01 21:31:42" 
    if (strftime(buffer, 25, "%Y", localtime(&seconds))) { 
     now << buffer; 
    } 
#endif // HAS_STD_PUT_TIME 
    return now.str(); 
} 

위의 작업은 내가 모든 패킷에 대해해야 할 일이다. 패킷 속도는 100000-1000000 pps이며 위의 코드는 currentYear()에서 매우 시간이 많이 걸립니다. 하나의 가능한 최적화는 currentYear() 메서드를 제거하고 연도 번호를 상수 값으로 저장하는 것입니다. 앞서 말했듯이 내 프로그램은 일 년 내내 운영되어야하며 2017 년이 다가오고 있음을 알고 있습니다. 우리는 2012 년 3 월 31 일 23:59:00에 바이너리를 바꿀 수 없으며 Year Number를 계산할 시간을 낭비하고 싶지 않습니다 !!

각 패킷에 대해 실행하지 않고 현재 연도 수를 계산하는보다 효율적인 방법이 필요합니다.

가능합니까? 나에 대한 당신의 제안은 무엇입니까?

+2

정확히 무엇이 가장 많은 시간을 차지했는지 프로파일 링 했습니까? 문자열 변환이라면 아이디어가 있지만 시간이 많이 걸릴지 확실하지 않을 수 있습니다. 또한 모듈러스는 일반적으로 값 비싼 연산입니다. – Hayt

+0

소스 타임 스탬프가 불완전한 경우이를 절대적으로 수행 할 수 없습니다. –

+3

C++ (C와 C++이 다른 언어 임)를 사용하고 있기 때문에 C 태그를 제거했고'auto '와'chrono' 라이브러리를 사용하기 때문에 C++ 11 태그를 추가했습니다 – wasthishelpful

답변

3

일단 현재 날짜와 시간을 얻었 으면이를 기반으로 다음 1 월 1 일 자정의 시간을 계산하는 것이 너무 어렵지 않습니다.

연도가 올라갈 때 예상되는 에포크 시간을 계산 한 후에는 로그 항목을 작성할 때 현재 시간과 비교하면됩니다. 미리 계산 된 1 월 1 일 자정에 이르지 않았다면 그 해가 아직 돌아 가지 않았 음을 알 수 있습니다.

따라서 모든 패킷에 대해 연도를 계산할 필요가 없습니다. 정치인이 귀하의 시간대를 변경하기로 결정하지 않으면 변경하지 않아야하는 미리 계산 된 1 월 1 일 자정 시간과 비교하여 현재 시간을 확인해야합니다 ...

+2

_"정치인이 결정하지 않는 한 이 모든 것이 실행되는 동안 시간대를 변경하십시오 ... "_ 동일한 해의 한 해 동안 도약 초가 발표 될 수는 없습니다. 사실 이것은 합리적으로 평범한 것입니다. 잠시 동안 "신기원"을 한 번 업데이트해야합니다. (나는 UTC라고 가정한다) –

+0

패킷 속도는 평균 500000ppps이다. 귀하가 제안한 "if"진술서가 얼마만큼 확인 될 것입니까? –

+1

@LightnessRacesinOrbit 이것은 당신의 타임 존이 윤년을 세는 "오른쪽/...."시간대 인 경우에만 해당됩니다. 이것은 실제로 매우 드뭅니다. 보통의 시간대는 윤초를 무시하고, ntpd는 시스템 시계를 천천히 내리고 속도를 늦추거나 하루의 속도를 빠르게하여 윤초를 흡수합니다. 신기원 이후 30 초가 넘는 윤초가 추가되었으며, 신기원 시간에 윤초가 포함되면 00 초 신기원 시간은 더 이상 60으로 나눌 수 없습니다.하지만 여전히 그렇습니다. TZ가 "America/New_York"대신에 "right/America/New_York"가 아니라면 말입니다. –

1

먼저 currentYear()을 반환 할 수 있습니다. int (예 : 2016), 아마도 time(2), localtime_r(3), tm_year 필드가 있습니다. 그러면 C++ 문자열을 만들지 않아도됩니다.

그런 다음 높은 패킷 속도를 말하는 것이므로 아마도 event loop이 될 것입니다. 어떻게 완료되었는지 설명하지 않습니다. (아마도 libevent 라이브러리를 사용하거나 최소한 자신의 루프를 poll(2) ....와 같이 사용하는 것이 좋겠지 만) 해당 이벤트 루프에서 현재 연도를 10 분의 1 초에 한 번만 계산할 수 있습니다 . 또는 현재 연도를 한 번씩 계산하는 다른 스레드가있을 수 있습니다 (아마도 뮤텍스가 필요하거나 std::atomic<int>을 현재 연도 유형으로 사용하십시오 ...)

1

Jan으로 시작하는 로그 항목의 연도가 변경됩니다. 해당 로그 항목 만

로그 항목이 때때로 순서가 잘못되거나 이전 처리 중에 저장된 타임 스탬프를 가지고 있습니다. PC의 시계에서 올해 부착

같은

 
2016 Dec 31 23:59:58 normal 
2016 Jan 01 00:01:01 printing time placed in packet by remote device, remote clock is running a bit fast 
2017 Dec 31 23:59:59 printing timestamp saved locally two seconds before logging occurred 
2017 Jan 01 00:00:03 back to normal 

당신은 그냥 달 로컬 클럭의 연도를 연결할 수 없습니다 ...의 두 번째 나쁜 결과를 줄 것이다 로그 메세지. 대형 시계 점프를 피하는 연도를 지정해야합니다.

어쨌든 유닉스 시간 (초후부터 초)을 만들려고하기 때문에 로그 메시지 시간을 줄리안 (초로 시작한 후 초)으로 바꾸고 줄리안이 1,000 만 개보다 작거나 큰지 테스트하십시오. (약 4 개월).

1

생성 한 문자열을 "캐시"하여 연도가 변경 될 때만 변경할 수 있습니다. 어떤 작업이 가장 많은 시간을 차지하는 지에 따라 "조금"개선 될 수도 있습니다.

//somewhere 
static int currentYear = 0; 
static std::string yearStr = ""; 

//in your function 
auto now = std::chrono::system_clock::now(); 
auto tnow = system_clock::to_time_t(now); 
auto lt = localtime(&tnow); //or gmtime depends on your needs. 
if(currentYear != lt.tm_year) 
{ 
    yearStr = std::to_string(lt.tm_year + 1900); 
    currentYear = t.tm_year; 
} 

return yearStr; 

나는 인해 캐시 지역에 여기 더있을 수 있습니다 정적 문자열 또는 멤버 변수를 읽기의 성능에 부정적/긍정적 인 측면이있는 경우없는 확신합니다. 이걸 시험해야 해.

이것을 여러 스레드에서 사용하는 경우 여기에서 뮤텍스를 사용해야합니다. 성능을 저하시킬 수 있습니다 (다시 측정해야 함).

관련 문제