2014-02-25 2 views
0

반복사전 구문 분석 (캐시)의 printf 스타일의 형식 문자열

의 printf/현재 snprintf/fprintf와/등 호출.

같은 형식 문자열이 있으며 인수 위치에 대한 각 호출에서 형식 문자열을 다시 채우는 것은 실제로 의미가 없습니다.

포맷 문자열을 구문 분석하고이를 printf 스타일 함수에 전달하여 처리 시간을 단축하는 기능을 제공하는 라이브러리를 아는 사람이 있습니까?

+5

당신이 상황으로 실행하셨습니까 '에서 가장 큰 병목 printf' 당신의 코드? – dasblinkenlight

+1

이것이 가장 큰 문제입니까, 아니면 성급하게 최적화하고 있습니까? 시나리오는 무엇입니까? –

+2

@ dasblinkenlight ... 그리고 이것은 파싱 때문이며 다음 출력으로 인한 것이 아닙니다. – Angew

답변

0

Boost.Format은 형식화 문자열을 구문 분석하여 한 번 포맷터 객체를 만든 다음 다시 사용할 수 있습니다. 구문 분석이 캐시되어 있지만 중간에 여러 개의 문자열 복사본이있는 것처럼 보이므로 더 빠를 것입니다.

printf 구현을 파싱 단계를 캐시하기 위해 사용할 수 있습니다. 이것은 상당한 절약을 생산할 것으로 보인다 유일한 상황은 다음과 같습니다

  • 대신 문자 단위 명시 폭과 정밀도의
  • 을 많이 복사하는 memecpy하기 수 오래되지 않은 형식의 리터럴 문자열이있는 경우 정수로 변환됩니다

기본적으로 printf 문자열은 구문 분석하기에 상당히 저렴하도록 설계되었으며 많은 중간 형식이 더 좋을지는 확실하지 않습니다.

+0

감사합니다. Boost.Format은 온라인에 게시 된 많은 벤치 마크에서 매우 느립니다. 나는 그것을 시도 할 것이다. – Graeme

2

대부분의 주식 printf 함수는 비교적 효율적입니다. 형식 문자열은 iostreams 및 Boot.Format에 의해 생성되는 많은 짧은 버퍼와 달리 단일의 일관된 소스이며, 대부분의 경우 (형식 문자열)은 대상 버퍼에 복사 할 대상의 대부분. "구문 분석"printf 형식은 상당히 저렴하지만, 실제로 printf 함수가 병목 현상이 있는지, printf 버퍼 관리가 좋지 않은 경우에는 비용이 많이 드는 형식을 알아야합니다. 그것은 필연적으로 전송

snprintf(thatBuffer, someSize, "[%u/%u/%u %u:%u:%u.%llu %s:%u] %p %s %f", 
    /* a 2-cacheline date object */ date->dy, date->mo, date->yr, date->hr, date->mi, date->sec, date->ms, 
    __FUNCTION__, __LINE__, // why didn't you embed those in the format? 
    object->ptr,   // another cache line 
    message,    // string from somewhere on the heap, page fault, 
    floaty     // floats and doubles are usually expensive 
    ); 

의 공정한 금액을 포함하고 우리는 심지어 어떤 공상 서식을 사용하지 않았기 때문에

자주, printf와/현재 snprintf 샘플링 프로필에 표시됩니다.

  • 이 제한 마스크와 자신의 단순화 printf와 쓰기 일관 하위 버퍼를 구축하려고 :

    는 인쇄를 최적화 할 수있는 몇 가지가 있습니다.

  • 를 사용하여 C++ (11) 가변 인자 템플릿은 'vsnprintf'GCC 4.8.2, 연타 3에서, (나는 미친 양으로이 향상시킬 수있는 성능을 발견했습니다) 예를 들어

전달을 방지 할 수 있습니다.다음 5 년과 2013 년 MSVC는 :

template<typename... Args> 
int formatText(const char* const fmt, Args&&...) 
{ 
    int len = std::min(snprintf(m_text, m_textSize, fmt, std::forward<Args>(args)...), m_textSize); 
    m_text[len] = '\0'; 
    return len; 
} 

은 나를 위해 다음과 같은보다 3 배 빠른 벤치 마크 : 당신의 프로파일 러가 지적 할 때

int inline formatText(const char* const fmt, ...) 
{ 
    va_list args; 
    va_start(args, fmt); 
    int len = std::min(vsnprintf(m_text, m_textSize, fmt, args), m_textSize); 
    va_end(args); 
    m_text[len] = '\0'; // assume m_textSize is storage size - sizeof('\0') 
    return len; 
}