Friday, March 6, 2015

Digest for comp.lang.c++@googlegroups.com - 21 updates in 4 topics

Christopher Pisz <nospam@notanaddress.com>: Mar 05 07:11PM -0600

On 3/5/2015 4:47 PM, Victor Bazarov wrote:
 
> Still, the only way to know for sure why the iterator method is slower
> is to profile it.
 
> V
 
 
So, I got Xperf to work after watching a few hours of videos and working
through a lot of out of date information.
 
It reports that
Method 1 has 44 heap allocations for a size of 217,357.
Method 2 has 26 heap allocations for a size of 194,437.
 
I rely on my high precision timer for the time of execution for both.
 
Method 1 :0.283209
Method 2 :0.0216563
 
I can't really find anything about istream_iterator or std::inserter
though. I like the code in method 1, it feels cleaner. I want to
understand if there is another step I am missing or something else I can
do similar.
 
It is fairly often I'd want to copy the contents of one stream to a
string or to another stream.
 
 
 
--
I have chosen to troll filter/ignore all subthreads containing the
words: "Rick C. Hodgins", "Flibble", and "Islam"
So, I won't be able to see or respond to any such messages
---
Paavo Helde <myfirstname@osa.pri.ee>: Mar 05 11:55PM -0600

Christopher Pisz <nospam@notanaddress.com> wrote in
> Method 2 :0.0216563
 
> That's quite a difference! What's going on under the hood with the
> iterator method?
 
The stream classes are meant for reading and writing *formatted* text at
high level (streaming a sequence of C++ objects of arbitrary classes to
and from a file). The current locale is taken into account on every step,
end-of-line conversions done, etc. The iterator works in this layer even
if it actually does no transformations. I would not be surprised if there
were a couple of virtual function calls involved with reading each
character.
 
OTOH, by using rdbuf() you actually say that you do not want all that
formatting and translation and want just to get the file content as it is
on the disk. Naturally this is a lot faster.
 
Still, I would expect a difference of at most 3-4 times, the stream
abstractions are not that bad. Looks like you are testing non-optimized
code. Also, the times like 0.02 seconds are too close to the OS process
scheduling granularity, plus the effects from OS file caching may show
up. I would put some loops in main() to get larger times, and the very
first runs of both methods should be ignored.
 
hth
Paavo
Juha Nieminen <nospam@thanks.invalid>: Mar 06 08:19AM

> std::copy(std::istream_iterator<char>(file),
> std::istream_iterator<char>(),
> std::inserter(textToParse, textToParse.begin()));
 
What's the problem with
 
std::string textToParse(std::istream_iterator<char>(file),
std::istream_iterator<char>());
 
--- news://freenews.netfront.net/ - complaints: news@netfront.net ---
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Mar 06 01:29PM

On 6 Mar 2015 12:17:09 GMT
> to merge them into a single statement.
> So, the requirement of »one statement«
> really is no requirement.
 
Well at least Christopher does not take the approach of answering a
question where the intent is obvious but the wording slightly amiss
with a pedantically correct but completely useless answer.
 
I think it is generally better to be helpful than to try to be "clever".
 
Chris
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Mar 06 02:28PM

On 6 Mar 2015 13:59:11 GMT
> »line« or »statement«, it is better to learn it
> (when posting into a technical programming newsgroup),
> than to accuse others.
 
Then let me meet pedantry with pedantry. Christopher did not "accuse
others". So far as there was an accusation (which seems a somewhat
paranoid view of the world on your part) it came from me. On other
hand, I did not use the words 'line' or 'statement', the failure to
understand which you criticize as forfeiting the right to criticize.
 
You knew full well that when Christopher referred to "statement" he
meant a non-compound statement, or possibly "expression".
 
I am afraid you have "previous" on this one.
 
Chris
Victor Bazarov <v.bazarov@comcast.invalid>: Mar 06 10:00AM -0500

On 3/5/2015 8:11 PM, Christopher Pisz wrote:
> do similar.
 
> It is fairly often I'd want to copy the contents of one stream to a
> string or to another stream.
 
I took your code and changed it a bit so I could time it on Windows. It
didn't have the ~14-fold difference like in your example, only about
1.5-fold (the iterator method taking longer by ~50%). Run your test
after building it in release (with optimization) and ensure that the
text file has been placed in the file cache (by running a couple times
and only noting the last run). Or swap the methods (call the 2 before
calling 1), just to be sure.
 
The operation is very quick on Windows with shorter files, so profiling
here doesn't make much sense. I would venture to point out, though that
the iterator method makes more function calls, probably.
 
And, after all, it's QoI of the library, of course.
 
V
--
I do not respond to top-posted replies, please don't ask
Christopher Pisz <nospam@notanaddress.com>: Mar 06 10:54AM -0600

On 3/6/2015 2:19 AM, Juha Nieminen wrote:
 
> std::string textToParse(std::istream_iterator<char>(file),
> std::istream_iterator<char>());
 
> --- news://freenews.netfront.net/ - complaints: news@netfront.net ---
 
Just that I don't know it, but that looks to be better.
So, taking your suggestions in combination with Victor's, here is my
current listing:
 
 
// Shared Includes
#include "Exception.h"
#include "PerformanceTimer.h"
 
// Standard Includes
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
 
const unsigned int NUM_ITERATIONS = 100;
 
//--------------------------------------------------------------------------------------------------
void Method1()
{
std::ifstream file("test.txt");
if( !file )
{
// Error
throw Shared::Exception(__FILE__, __LINE__, "Cannot open test
file");
}
 
std::string textToParse(std::istream_iterator<char>(file),
std::istream_iterator<char>());
 
file.close();
}
 
//--------------------------------------------------------------------------------------------------
void Method2()
{
std::ifstream file("test.txt");
if( !file )
{
// Error
throw Shared::Exception(__FILE__, __LINE__, "Cannot open test
file");
}
 
std::string textToParse;
 
file >> std::noskipws;
std::copy(std::istream_iterator<char>(file),
std::istream_iterator<char>(),
std::inserter(textToParse, textToParse.begin()));
 
file.close();
}
 
//--------------------------------------------------------------------------------------------------
void Method3()
{
std::ifstream file("test.txt");
if( !file )
{
// Error
throw Shared::Exception(__FILE__, __LINE__, "Cannot open test
file");
}
 
std::stringstream textToParse;
textToParse << file.rdbuf();
 
file.close();
}
 
//--------------------------------------------------------------------------------------------------
int main()
{
Method1();
Method2();
Method3();
 
Shared::PerformanceTimer timer;
for(unsigned count = 0; count < NUM_ITERATIONS; ++count)
{
Method1();
}
std::cout << "Method 1 :" << timer.Stop() << std::endl;
 
timer.Start();
for(unsigned count = 0; count < NUM_ITERATIONS; ++count)
{
Method2();
}
std::cout << "Method 2 :" << timer.Stop() << std::endl;
 
timer.Start();
for(unsigned count = 0; count < NUM_ITERATIONS; ++count)
{
Method3();
}
std::cout << "Method 3 :" << timer.Stop() << std::endl;
}
 
 
and the output is:
Method 1 :0.012716
Method 2 :0.361421
Method 3 :0.141371
 
 
 
--
I have chosen to troll filter/ignore all subthreads containing the
words: "Rick C. Hodgins", "Flibble", and "Islam"
So, I won't be able to see or respond to any such messages
---
Christopher Pisz <nospam@notanaddress.com>: Mar 06 11:06AM -0600

On 3/6/2015 10:54 AM, Christopher Pisz wrote:
> Method 1 :0.012716
> Method 2 :0.361421
> Method 3 :0.141371
 
I take it back, something is fruity with Juha's suggestion. I see a
warning "warning C4930: 'std::string
textToParse(std::istream_iterator<_Ty>,std::istream_iterator<_Ty>
(__cdecl *)(void))': prototyped function not called (was a variable
definition intended?)" and cannot seem to use the string afterward
without compiler errors that claim it isn't a compatible type. I don't
follow. Using msvc 2012.
 
 
--
I have chosen to troll filter/ignore all subthreads containing the
words: "Rick C. Hodgins", "Flibble", and "Islam"
So, I won't be able to see or respond to any such messages
---
Victor Bazarov <v.bazarov@comcast.invalid>: Mar 06 02:56PM -0500

On 3/6/2015 12:06 PM, Christopher Pisz wrote:
> definition intended?)" and cannot seem to use the string afterward
> without compiler errors that claim it isn't a compatible type. I don't
> follow. Using msvc 2012.
 
Change that line to read
 
std::string textToParse(std::istream_iterator<char>{file},
std::istream_iterator<char>{});
 
(note the curly braces), and don't use pre-C++11 compiler :-)
 
(actually I'm not sure it's going to work with VC++ 2012, I used 2013
and got this result:
 
Method 1 :498549
Method 2 :305819
Method 3 :110364
 
(with an 18K file, and those are the processor ticks, using the Windows
QueryPerformanceCounter)
 
How big is your file?
 
Another note: make sure the optimizer does not throw away the result of
the Method1. It's quite possible that since you're not returning it
anywhere, the optimizer might change the code to never create the object
in the first place. Think of returning the string from those functions
(as in 'std::string Method1(...')
 
Here is my (corrected) code:
//--------------------------------------------------------------------------------------------------
// Standard Includes
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <cstdio>
#include <Windows.h>
 
const unsigned int NUM_ITERATIONS = 100;
 
//--------------------------------------------------------------------------------------------------
std::string Method1()
{
std::ifstream file("test.txt");
if (!file)
{
// Error
throw 1;
}
 
std::string textToParse(std::istream_iterator < char > {file},
std::istream_iterator < char > {});
 
file.close();
 
return textToParse;
}
 
//--------------------------------------------------------------------------------------------------
std::string Method2()
{
std::ifstream file("test.txt");
if (!file)
{
// Error
throw 22;
}
 
std::string textToParse;
 
file >> std::noskipws;
std::copy(std::istream_iterator<char>(file),
std::istream_iterator<char>(),
std::inserter(textToParse, textToParse.begin()));
 
file.close();
 
return textToParse;
}
 
//--------------------------------------------------------------------------------------------------
std::string Method3()
{
std::ifstream file("test.txt");
if (!file)
{
// Error
throw 333;
}
 
std::stringstream textToParse;
textToParse << file.rdbuf();
 
file.close();
 
return textToParse.str();
}
 
//--------------------------------------------------------------------------------------------------
int main()
{
Method1();
Method2();
Method3();
 
LARGE_INTEGER t0, t1;
QueryPerformanceCounter(&t0);
for (unsigned count = 0; count < NUM_ITERATIONS; ++count)
{
Method1();
}
QueryPerformanceCounter(&t1);
std::cout << "Method 1 :" << t1.QuadPart - t0.QuadPart << std::endl;
 
QueryPerformanceCounter(&t0);
for (unsigned count = 0; count < NUM_ITERATIONS; ++count)
{
Method2();
}
QueryPerformanceCounter(&t1);
std::cout << "Method 2 :" << t1.QuadPart - t0.QuadPart << std::endl;
 
QueryPerformanceCounter(&t0);
for (unsigned count = 0; count < NUM_ITERATIONS; ++count)
{
Method3();
}
QueryPerformanceCounter(&t1);
std::cout << "Method 3 :" << t1.QuadPart - t0.QuadPart << std::endl;
}
//--------------------------------------------------------------------------------------------------
 
V
--
I do not respond to top-posted replies, please don't ask
Luca Risolia <luca.risolia@linux-projects.org>: Mar 06 10:32PM +0100

Il 06/03/2015 18:06, Christopher Pisz ha scritto:
> definition intended?)" and cannot seem to use the string afterward
> without compiler errors that claim it isn't a compatible type. I don't
> follow.
 
According to the language rules "std::istream_iterator<char>()" is a
declaration of "function taking no arguments returning
istream_iterator<char>". To force the compiler to treat the construct as
an expression surround it with extra parentheses:
 
std::string
textToParse(std::istream_iterator<char>(file),(std::istream_iterator<char>()));
Victor Bazarov <v.bazarov@comcast.invalid>: Mar 06 05:09PM -0500

On 3/6/2015 4:32 PM, Luca Risolia wrote:
> an expression surround it with extra parentheses:
 
> std::string
> textToParse(std::istream_iterator<char>(file),(std::istream_iterator<char>()));
 
And to expand on that, the sequence of tokens
std::istream_iterator<char>(file)
can be also treated as a declaration of an object called 'file' of type
'istream_iterator<char>', the parentheses are superfluous and ignored.
Thus the entire original declaration of 'textToParse' is a declaration
of a function that takes two arguments and returns a std::string. The
name of the first argument ("file") in that case is ignored.
 
V
--
I do not respond to top-posted replies, please don't ask
Robert Wessel <robertwessel2@yahoo.com>: Mar 05 09:33PM -0600

>> 969 years.
 
>Oldest human was Methuselah. They knew how to take
>care of themselves and others.
 
 
Even if you make the (rather big) assumption that the bible has
historical accuracy, it does not assert that Methuselah was the oldest
human, but he is the oldest it mentions, and perhaps the oldest in the
genealogy leading to Noah, although that's still something of a
stretch.
woodbrian77@gmail.com: Mar 05 09:53PM -0800

> human, but he is the oldest it mentions, and perhaps the oldest in the
> genealogy leading to Noah, although that's still something of a
> stretch.
 
OK, oldest documented human was Methuselah.
Robert Wessel <robertwessel2@yahoo.com>: Mar 06 02:45AM -0600

>> genealogy leading to Noah, although that's still something of a
>> stretch.
 
>OK, oldest documented human was Methuselah.
 
 
Nah.
 
Just hanging around the middle east...
 
En-men-lu-ana, a king of Sumar, reigned for 43,200 years. Presumably
he was alive during that time. There are a bunch of other Sumarian
kings who hung around a really long time.
 
Aži Dahaka ruled for a thousand years. Just ask the Zoroastrians.
David Brown <david.brown@hesbynett.no>: Mar 06 09:49AM +0100

>> genealogy leading to Noah, although that's still something of a
>> stretch.
 
> OK, oldest documented human was Methuselah.
 
There were equally well documented Sumerian kings who ruled for tens of
thousands of years each. The authors of the books of Moses took a lot
of inspiration from Sumerian stories and legends - they probably copied
the habit of exaggerating lifespans too.
 
Other old documented humans include some ancient Persian kings, as well
as many characters from India and the far east.
 
Remember, "documented" does not mean "true" !
Stuart Redmann <DerTopper@web.de>: Mar 06 04:28PM

JiiPee wrote:
 
[snip]
 
> private:
> float f;
> };
 
Actually, that's a Really Good Idea (TM). That's what Ada95 has in
advantage of C++, you can create real number types quite easily. Lot's of
bugs would never have occurred had the program been written in Ada, like
the infamous bug in libTIFF, where the number of bytes to be copied from a
section was computed as int variable. Since the size of the section is
stored in the TIFF file including the 4 bytes of the section header, the
int variable had to be decreased by 4. If a malicious attacker created a
TIFF file, where the section size was stored with a value <4, the int
variable became negative, so that it got interpreted as UINT_MAX. LibTIFF
would then try to copy that many bytes from the TIFF file, which could lead
to stack corruption and privilege escalation.
 
This would never have happened in an Ada95 program, because the data type
"Integer" is always the last choice for a variable. Unfortunately, C++ did
not offer an equally easy way to define numeric data types (typedef is
insufficient there) :-(
 
Another thing is the source of many (avoidable) errors is implicit type
conversions. More than one time I shot myself in the foot by passing
inadvertently a float into a parameter that should actually be a bool. That
passes compilation totally unnotized. Had I tried to pass a Float for a
Bool, my folly would have been recognized on the spot.
 
I know that it is easily possible to create a matching type system in C++,
but unfortunately the C++ "mindset" has already been poisoned with the
wide-spread usage of the native data types like int and float.
 
Just my 2cents.
Stuart
 
PS: Please don't mistake me for a C++ hater. I love it heartily. I just
wish that it wouldn't spring so many traps.
ram@zedat.fu-berlin.de (Stefan Ram): Mar 06 12:05AM

Sorry, I have tried to search for »scope« in the C++
specification, but there are very many hits, and I gave up!
 
Maybe some reader already knows the answer:
 
It seems that the scope of »i« begins at the place
of the comment in the following program.
 
constexpr int f( int const * const p ){ return 2; }
int main(){ constexpr int i/**/{ f( &i ) }; }
 
Now, I would like to know the location in the C++
specification where this is specified.
ram@zedat.fu-berlin.de (Stefan Ram): Mar 06 12:17PM

>>it's simple, because the rest of the program can always be written
>>in a single line
>Statement. One statement.
 
Whenever one has multiple statements,
one can use a compound statement (block)
to merge them into a single statement.
So, the requirement of »one statement«
really is no requirement.
ram@zedat.fu-berlin.de (Stefan Ram): Mar 06 01:54PM

>Well at least Christopher does not take the approach of answering a
>question where the intent is obvious but the wording slightly amiss
>with a pedantically correct but completely useless answer.
 
If the intent is obvious, then maybe someone can write it down?
 
»While sloppy writing does not invariably mean sloppy
thinking, we've generally found the correlation to be
strong -- and we have no use for sloppy thinkers.
If you can't yet write competently, learn to.«
 
Eric Raymond
 
http://www.catb.org/~esr/faqs/hacker-howto.html#skills4
 
»I have never, ever, ever seen a great software developer
who does not have amazing attention to detail.«
 
http://www.softwarebyrob.com/articles/Personality_Traits_of_the_Best_Software_Developers.aspx
ram@zedat.fu-berlin.de (Stefan Ram): Mar 06 01:59PM

>I think it is generally better to be helpful than to try to be "clever".
 
When one does not know the meaning of words like
»line« or »statement«, it is better to learn it
(when posting into a technical programming newsgroup),
than to accuse others.
"Öö Tiib" <ootiib@hot.ee>: Mar 05 04:44PM -0800

On Friday, 6 March 2015 02:06:22 UTC+2, Stefan Ram wrote:
 
> Maybe some reader already knows the answer:
 
> It seems that the scope of »i« begins at the place
> of the comment in the following program.
 
Yes.
 
> int main(){ constexpr int i/**/{ f( &i ) }; }
 
> Now, I would like to know the location in the C++
> specification where this is specified.
 
[basic.scope.block] Says that scope of your i starts from
"point of declaration".
[basic.scope.pdecl] tells that the "point of declaration"
of your i is immediately after it and before its initializer.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: