none
Performance issue of double to string conversion using _snprintf_l c++

    Question

  • Hi,

    Below double to string conversion takes long time. around 2 minutes. (using vs2013, c++ ). Please suggest any other utilities to improve the performance.

    I have to call this doubleToStringWithPrecision2 function million times.


     std::string doubleToStringWithPrecision2(double value)
    {
       char array[32];
       _snprintf_l(array, 32, "%.2f", currentLocale.get(), value);
       return array;

    // currentLocale is unique ptr to current application locale  (_locale_t)

    // decimal separator can be dot or comma  based on the locale 


    }

    void Test_function()

    {

       for (unsigned long k = 0; k < (250000000); k++)
       {
          std::string kk = doubleToStringWithPrecision2(22.223);
       }

    }





    • Edited by Uralsib Wednesday, March 07, 2018 5:17 AM
    Wednesday, March 07, 2018 4:03 AM

All replies

  • Below double to string conversion takes long time. around 2 minutes. (using vs2013, c++ ).

    I have to call this doubleToStringWithPrecision2 function million times.

     std::string doubleToStringWithPrecision2(double value)
    {
       char array[32];
       _snprintf_l(array, 32, "%.2f", currentLocale.get(), value);
       return array;

    // cLocale is unique ptr to current application locale  (_locale_t)


    First off, provide some specifics:

    Are your timing results from execution of a Debug version of your
    program, or a Release version? If a Debug version, build a Release
    version and time that. There can be a lot of overhead in Debug versions
    of a program.

    >// cLocale is unique ptr to current application locale  (_locale_t)

    What is cLocale? I don't see it anywhere in the code you posted.
    Or did you mean currentLocale?

    Note that if currentLocale.get() is a function call, you should get
    a performance improvement if you did that call once before the loop
    begins.

    - Wayne

    Wednesday, March 07, 2018 4:51 AM
  • Below double to string conversion takes long time. around 2 minutes. (using vs2013, c++ ). Please suggest any other utilities to improve the performance.

    I have to call this doubleToStringWithPrecision2 function million times.

     std::string doubleToStringWithPrecision2(double value)
    {

    Have you tried using __forceinline on your doubleToStringWithPrecision2 function?

    inline, __inline, __forceinline
    Visual Studio 2013
    https://msdn.microsoft.com/en-us/library/z8y1yy88(v=vs.120).aspx

    - Wayne

    Wednesday, March 07, 2018 4:58 AM
  • // currentLocale is unique ptr to current application locale  (_locale_t)

    // currentLocale.get()  gets the raw pointer 

    auto currentLocale = std::unique_ptr<_locale_tstruct, std::function<void(_locale_t)>>(_create_locale(LC_ALL, "C"), [](_locale_t l) { _free_locale(l); });

    Wednesday, March 07, 2018 5:15 AM
  • using release version . __forceinline  has not much effect.
    • Edited by Uralsib Wednesday, March 07, 2018 5:21 AM
    Wednesday, March 07, 2018 5:16 AM
  • From profiling it seems _snprintf_l()  takes most of the time.
    Wednesday, March 07, 2018 5:24 AM
  • From profiling it seems _snprintf_l()  takes most of the time.

    Try profiling using _snprintf instead of _snprintf_l and see if it has
    about the same overhead.

    //_snprintf_l(array, 32, "%.2f", currentLocale.get(), value);
    _snprintf(array, 32, "%.2f", value);

    - Wayne

    Wednesday, March 07, 2018 5:31 AM
  • Not much difference with _snprintf function. (around 2 minutes) 
    • Edited by Uralsib Wednesday, March 07, 2018 5:52 AM
    Wednesday, March 07, 2018 5:50 AM
  • profile with snprintf_1
    Wednesday, March 07, 2018 5:51 AM
  • Hello,

    look at this routine: https://www.menie.org/georges/embedded/small_printf_source_code.html

    There is a sprintf too.

    Regards, Guido

    Wednesday, March 07, 2018 7:13 AM
  • No difference .

    There is a sprintf too.

    Wednesday, March 07, 2018 10:59 AM
  • Below double to string conversion takes long time. around 2 minutes. (using vs2013, c++ ). Please suggest any other utilities to improve the performance.

    Looking around, the consensus seems to be that the 'C' function you're using already gives the best performance for general purpose
    use. There's probably little you can do to make a marked improvement, other than avoiding any heap usage with std:string.

    I have to call this doubleToStringWithPrecision2 function million times.

    Could you make use of multiple threads?

    Dave

    Wednesday, March 07, 2018 12:11 PM
  • From the profiling results it is clear that sprintf_l is taking most of the time.  Not clear why this call taking this much time.
    • Edited by Uralsib Wednesday, March 07, 2018 1:14 PM
    Wednesday, March 07, 2018 1:13 PM
  • From the profiling results it is clear that sprintf_l is taking most of the time.  Not clear why this call taking this much time.

    If you want to feel better about the time _snprintf_l takes - or at least
    accept the premise that it's fairly well optimized - time an alternative
    method. Perhaps something like:

    std::stringstream ss;
    ss << value;
    std::string s;
    ss >> s;
    
    return s;
    

    or perhaps

    std::ostringstream buf;
    buf << value;
    std::string s = buf.str();
    
    return s;
    

    I'll wager that these and most (perhaps all) other methods take more time
    than _snprintf_l.

    - Wayne

    Wednesday, March 07, 2018 1:42 PM
  • void Test_function()

    {

       for (unsigned long k = 0; k < (250000000); k++)
       {
          std::string kk = doubleToStringWithPrecision2(22.223);
       }

    }

    Your Test_function iterates 250 million times. Are you really going to
    need to call it that often in your real program?

    - Wayne

    Wednesday, March 07, 2018 1:50 PM
  • >From the profiling results it is clear that sprintf_l is taking most of the time.  Not clear why this call taking this much time.

    It's not a trivial thing to do - try writing it yourself :)

    Wednesday, March 07, 2018 1:50 PM
  • Yes. My real application needs to call 250000000 times.
    Wednesday, March 07, 2018 2:08 PM
  • Actually (real application) i want write 250000000 double values to  a text file after setting precision to 2
    Wednesday, March 07, 2018 2:09 PM
  • Actually (real application) i want write 250000000 double values to  a text file after setting precision to 2

    I think, writing to a text file is much more time consuming than sprintf. Did you check this? How much time does writing of 250 million double values to the file need?

    Why don't you only write the doubles directly to the file instead of converting them to string first?

    Wednesday, March 07, 2018 2:30 PM
  • From the profiling graph above, it is evident that  most of the time consumed for sprintf_l function (95% of total time). 
    Thursday, March 08, 2018 3:57 AM
  • From the profiling graph above, it is evident that  most of the time consumed for sprintf_l function (95% of total time). 

    Ok. It was not obvious enough to me that you already checked with file IO.

    You only want to write to a text file. What happens if you don't cast to string but only use fstream precision?

    std::ofstream fo;
    fo.open(_T("thefile.txt");
    if (!fo.is_open()) return;
    fo.precision(2);
    for (unsigned long k = 0; k < (250000000); k++)
    {
      fo << 22.223 << '\n';
    }
    fo.close();

    Regards, Guido



    Thursday, March 08, 2018 8:50 AM
  • No much effect. 
    Thursday, March 08, 2018 12:43 PM
  • If I remember right, this was a well known issue in VS2013 and older because of the way the sprint family of functions were implemented. As written in this blog post:

    "Before this refactoring, the sprintf functions, which write formatted data to a character buffer, were implemented by wrapping the result buffer in a temporary FILE object and then deferring to the equivalent fprintf function. This worked and produced the correct result, but it was exceedingly inefficient. When writing characters to a FILE we need to be careful to handle many cases like buffer exhaustion, end-of-line conversions, and character conversions. When writing characters to a string, we should simply be able to write through and increment the result pointer. After the refactoring, we were easily able to identify this performance problem and, more importantly, fix it. The sprintf functions are now up to 8 times faster than they were in previous releases."

    So unfortunately, you are going to have to switch to using Visual Studio 2017 or 2015 to use the updated UCRT implementation to get any performance improvements.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Thursday, March 08, 2018 3:10 PM
  • Then try _fcvt or _ecvt.

    -- pa

    Thursday, March 08, 2018 5:26 PM
  • From the profiling graph above, it is evident that  most of the time consumed for sprintf_l function (95% of total time). 


    Well that may be perfectly understandable - if the program isn't doing
    anything else that is computationally intensive. Consider your test
    code previously posted. If that is basically all that is in the tested
    program then of course _sprintf_l will account for almost 100% of the
    cpu time used by the program. What else is there in the program that is
    cpu intensive? Just a for loop?

    Out of a total of all cpu time used by your program (100%), what percentage
    do you think the conversion from a double to a string should take? What
    other operations in the program do you think should take a greater percentage
    of cpu usage than they are currently showing?

    The results - in terms of percentage of total cpu time used - will always
    be close to 100% for the conversion, regardless of what method is used.
    How could it be otherwise when there is nothing else in the program that
    requires much cpu time?

    If you want to see the cpu % used by _sprintf_l drop dramatically in the
    profiling, then add code which also is cpu-intensive. For example, in
    the test code previously posted include two conversion functions. One
    using the _sprintf_l function as originally, and the other doing the
    exact same looping but using an alternative conversion method.

    Call both functions - either from within the same loop or within
    different loops - so that both methods are executed the same number
    of times during a single run of the test program.

    Profile it. You should see the usage % of _sprintf_l drop dramatically
    as now there is another operation that also requires a significant amount
    of cpu time.

    - Wayne

    Friday, March 09, 2018 1:39 AM
  • Hi,

    Has your case been solved? If it has, please help to mark answer. If not, just feel free to contact us.

    Your understanding and cooperation will be grateful.

    Best Regards,

    Baron Bi


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, March 16, 2018 7:39 AM
    Moderator