Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #97957 > unrolled thread

Counted strings

Started byjacobnavia <jacob@jacob.remcomp.fr>
First post2016-12-03 23:58 +0100
Last post2016-12-10 11:08 -0800
Articles 20 on this page of 111 — 24 participants

Back to article view | Back to comp.lang.c


Contents

  Counted strings jacobnavia <jacob@jacob.remcomp.fr> - 2016-12-03 23:58 +0100
    Re: Counted strings supercat@casperkitty.com - 2016-12-03 15:40 -0800
    Counted stringsl Thiago Adams <thiago.adams@gmail.com> - 2016-12-03 15:40 -0800
    Re: Counted strings BartC <bc@freeuk.com> - 2016-12-04 00:20 +0000
    Re: Counted strings Richard Damon <Richard@Damon-Family.org> - 2016-12-03 21:26 -0500
      Re: Counted strings jacobnavia <jacob@jacob.remcomp.fr> - 2016-12-04 18:11 +0100
      Re: Counted strings Mark Storkamp <mstorkamp@yahoo.com> - 2016-12-04 19:25 -0600
    Re: Counted strings Keith Thompson <kst-u@mib.org> - 2016-12-03 18:57 -0800
    Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-04 16:33 +0100
      Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-04 07:52 -0800
        Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-04 17:10 +0100
          Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-04 10:14 -0800
            Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-04 20:20 +0100
              Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-04 16:49 -0800
                Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-05 10:40 +0100
                  Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 05:51 -0800
                    Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-05 16:10 +0100
                      Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 07:38 -0800
                        Re: Counted strings Melzzzzz <mel@zzzzz.com> - 2016-12-05 16:56 +0100
                          Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 08:04 -0800
                            Re: Counted strings Melzzzzz <mel@zzzzz.com> - 2016-12-05 17:16 +0100
                            Re: Counted strings Jerry Stuckle <jstucklex@attglobal.net> - 2016-12-05 16:12 -0500
                              Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 13:24 -0800
                                Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-06 10:53 +0100
                                  Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 03:52 -0800
                                    Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-06 13:32 +0100
                                      Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 04:48 -0800
                                    Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-06 13:42 +0100
                                      Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 05:16 -0800
                                        Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-06 14:39 +0100
                                      Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 05:24 -0800
                                        Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 05:41 -0800
                                          Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 05:47 -0800
                                        Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-06 14:48 +0100
                                          Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 05:54 -0800
                                            Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 06:21 -0800
                                              Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 06:24 -0800
                                            Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-06 18:06 +0100
                                              Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 10:19 -0800
                                                Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-06 19:45 +0100
                                                  Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 11:10 -0800
                                                    Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 12:58 -0800
                                                    Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 14:08 -0800
                                              Re: Counted strings Keith Thompson <kst-u@mib.org> - 2016-12-06 11:25 -0800
                                      Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 05:28 -0800
                                  Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-06 16:21 +0100
                                    Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 07:29 -0800
                                    Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 07:39 -0800
                                      Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 08:32 -0800
                                      Re: Counted strings fir <profesor.fir@gmail.com> - 2016-12-06 08:32 -0800
                        Re: Counted strings BartC <bc@freeuk.com> - 2016-12-05 16:28 +0000
                          Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 08:34 -0800
                            Re: Counted strings BartC <bc@freeuk.com> - 2016-12-05 18:27 +0000
                              Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 10:36 -0800
                              Re: Counted strings Ian Collins <ian-news@hotmail.com> - 2016-12-06 08:19 +1300
                                Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 11:22 -0800
                                  Re: Counted strings Ian Collins <ian-news@hotmail.com> - 2016-12-06 08:26 +1300
                                Re: Counted strings BartC <bc@freeuk.com> - 2016-12-05 19:36 +0000
                                  Re: Counted strings Ian Collins <ian-news@hotmail.com> - 2016-12-06 08:41 +1300
                                    Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 11:48 -0800
                                      Re: Counted strings Thiago Adams <thiago.adams@gmail.com> - 2016-12-05 11:59 -0800
                                      Re: Counted strings jameskuyper@verizon.net - 2016-12-05 12:12 -0800
                                        Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 12:18 -0800
                                          Re: Counted strings jameskuyper@verizon.net - 2016-12-05 13:17 -0800
                                            Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 13:29 -0800
                                              Re: Counted strings jameskuyper@verizon.net - 2016-12-05 15:37 -0800
                                                Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 15:43 -0800
                                                Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-06 13:40 +0100
                                                  Re: Counted strings "James R. Kuyper" <jameskuyper@verizon.net> - 2016-12-06 12:00 -0500
                                                    Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 10:09 -0800
                                                      Re: Counted strings Jerry Stuckle <jstucklex@attglobal.net> - 2016-12-06 13:33 -0500
                                                      Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-06 21:24 +0100
                                                        Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-06 12:56 -0800
                                Re: Counted strings Keith Thompson <kst-u@mib.org> - 2016-12-05 12:22 -0800
                          Re: Counted strings supercat@casperkitty.com - 2016-12-05 08:36 -0800
                            Re: Counted strings BartC <bc@freeuk.com> - 2016-12-05 17:31 +0000
                              Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-05 22:07 +0100
                            Re: Counted strings Ian Collins <ian-news@hotmail.com> - 2016-12-06 10:14 +1300
                          Re: Counted strings Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-05 22:11 +0000
                            Re: Counted strings BartC <bc@freeuk.com> - 2016-12-06 02:13 +0000
                        Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-05 21:57 +0100
                          Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 13:01 -0800
                          Re: Counted strings BartC <bc@freeuk.com> - 2016-12-05 21:22 +0000
                            Re: Counted strings Ian Collins <ian-news@hotmail.com> - 2016-12-06 10:25 +1300
                              Re: Counted strings BartC <bc@freeuk.com> - 2016-12-05 21:36 +0000
                          Re: Counted strings jacobnavia <jacob@jacob.remcomp.fr> - 2016-12-05 22:33 +0100
                            Re: Counted strings "Rick C. Hodgin" <rick.c.hodgin@gmail.com> - 2016-12-05 17:03 -0500
      Re: Counted strings supercat@casperkitty.com - 2016-12-04 08:57 -0800
      Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-04 20:19 +0100
        Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-04 20:24 +0100
          Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-04 20:37 +0100
            Re: Counted strings David Brown <david.brown@hesbynett.no> - 2016-12-04 21:04 +0100
              Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-04 21:22 +0100
                Re: Counted strings BartC <bc@freeuk.com> - 2016-12-04 22:37 +0000
                Re: Counted strings David Thompson <dave.thompson2@verizon.net> - 2016-12-10 22:42 -0500
                  Re: Counted strings Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-12-10 23:17 -0800
                    Re: Counted strings Ben Bacarisse <ben.usenet@bsb.me.uk> - 2016-12-11 11:48 +0000
                      Re: Counted strings Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-12-11 04:40 -0800
                  Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-11 10:56 +0100
        Re: Counted strings Robert Wessel <robertwessel2@yahoo.com> - 2016-12-05 15:47 -0600
          Re: Counted strings Gareth Owen <gwowen@gmail.com> - 2016-12-05 22:01 +0000
            Re: Counted strings Robert Wessel <robertwessel2@yahoo.com> - 2016-12-05 22:28 -0600
          Re: Counted strings "Chris M. Thomasson" <invalid@invalid.invalid> - 2016-12-05 20:18 -0800
          Re: Counted strings Robert Spanjaard <spamtrap@arumes.com> - 2016-12-06 11:05 +0100
    Re: Counted strings luser droog <luser.droog@gmail.com> - 2016-12-04 13:13 -0800
    Re: Counted strings Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-12-05 09:30 -0800
      Re: Counted strings Keith Thompson <kst-u@mib.org> - 2016-12-05 09:41 -0800
        Re: Counted strings Malcolm McLean <malcolm.mclean5@btinternet.com> - 2016-12-06 11:19 -0800
          Re: Counted strings Keith Thompson <kst-u@mib.org> - 2016-12-06 11:44 -0800
    Re: Counted strings Tim Rentsch <txr@alumni.caltech.edu> - 2016-12-10 10:29 -0800
      Re: Counted strings supercat@casperkitty.com - 2016-12-10 11:08 -0800

Page 4 of 6 — ← Prev page 1 2 3 [4] 5 6  Next page →


#98053

FromThiago Adams <thiago.adams@gmail.com>
Date2016-12-05 11:59 -0800
Message-ID<f16de890-6b34-458f-b2d5-ac1bec7b67d6@googlegroups.com>
In reply to#98050
On Monday, December 5, 2016 at 5:48:36 PM UTC-2, Rick C. Hodgin wrote:
> On Monday, December 5, 2016 at 2:41:37 PM UTC-5, Ian Collins wrote:
> > On 12/ 6/16 08:36 AM, BartC wrote:
> > > On 05/12/2016 19:19, Ian Collins wrote:
> > >> On 12/ 6/16 07:27 AM, BartC wrote:
> > >>>
> > >>> I've tested the C again on Linux (as Windows C libraries are known to be
> > >>> slow). That is much better:
> > >>>
> > >>>              C/Win      C/Linux     Interpreted/Windows
> > >>>
> > >>> 10M       13         0.4         0.2  seconds
> > >>> 100M      ?          2.2         1.7
> > >>> 500M      ??        18.0        17.0
> > >>>
> > >>> However, the interpreted code is still faster...
> > >>
> > >> Or you could just use a horribly slow and bloated language like C++:
> > >>
> > >> #include <string>
> > >> #include <stdio.h>
> > >>
> > >> int main()
> > >> {
> > >>    std::string s;
> > >>
> > >>    for (int i=0; i<100000000; ++i) {
> > >>      s += 'A';
> > >>    }
> > >>
> > >>    printf("s.length      = %d\n",s.size());
> > >> }
> > >>
> > >>        C        C++     C(64bit)    C++(64Bit)
> > >> 500M  15.5     8.6     11.2        7.0
> > >
> > > What's the C timing; is that for my code?
> > >
> > > If so, it hasn't done too badly!
> > 
> > Yes.
> 
> Where's the source code for std::string?  I'd like to see how its
> allocator works.


Where is the source code for all those numbers?

std::string can use the called "small string optimization" apart of the job of allocators.
I think it is comparing bananas with apples.


[toc] | [prev] | [next] | [standalone]


#98058

Fromjameskuyper@verizon.net
Date2016-12-05 12:12 -0800
Message-ID<ade295c4-cf11-42e1-a063-75071bf84718@googlegroups.com>
In reply to#98050
On Monday, December 5, 2016 at 2:48:36 PM UTC-5, Rick C. Hodgin wrote:
> On Monday, December 5, 2016 at 2:41:37 PM UTC-5, Ian Collins wrote:
> > On 12/ 6/16 08:36 AM, BartC wrote:
> > > On 05/12/2016 19:19, Ian Collins wrote:
...
> > >> Or you could just use a horribly slow and bloated language like C++:
> > >>
> > >> #include <string>
> > >> #include <stdio.h>
> > >>
> > >> int main()
> > >> {
> > >>    std::string s;
> > >>
> > >>    for (int i=0; i<100000000; ++i) {
> > >>      s += 'A';
> > >>    }
> > >>
> > >>    printf("s.length      = %d\n",s.size());
> > >> }
> > >>
> > >>        C        C++     C(64bit)    C++(64Bit)
> > >> 500M  15.5     8.6     11.2        7.0
> > >
> > > What's the C timing; is that for my code?
> > >
> > > If so, it hasn't done too badly!
> > 
> > Yes.
> 
> Where's the source code for std::string?  I'd like to see how its
> allocator works.

std::string is a typedef for std::basic_string<char>, which leaves Allocator
unspecified. std::basic_string<charT, traits, Allocator> has a default value
for Allocator of std::allocator<charT>. The features of std::allocator<T> are
defined in section 20.8.9 of the C++ standard. In particular, the actual
allocation of memory is done by calling ::operator new(std::size_t). That
doesn't answer your question, but it does tell you which parts of the source
code you should be looking for.

Please don't ask me where to find those parts: I don't know any details at that level about any particular implementation of C++.

[toc] | [prev] | [next] | [standalone]


#98061

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2016-12-05 12:18 -0800
Message-ID<45762735-e92c-401a-9d42-f73d7d276f8a@googlegroups.com>
In reply to#98058
On Monday, December 5, 2016 at 3:13:01 PM UTC-5, james...@verizon.net wrote:
> On Monday, December 5, 2016 at 2:48:36 PM UTC-5, Rick C. Hodgin wrote:
> > On Monday, December 5, 2016 at 2:41:37 PM UTC-5, Ian Collins wrote:
> > > On 12/ 6/16 08:36 AM, BartC wrote:
> > > > On 05/12/2016 19:19, Ian Collins wrote:
> ...
> > > >> Or you could just use a horribly slow and bloated language like C++:
> > > >>
> > > >> #include <string>
> > > >> #include <stdio.h>
> > > >>
> > > >> int main()
> > > >> {
> > > >>    std::string s;
> > > >>
> > > >>    for (int i=0; i<100000000; ++i) {
> > > >>      s += 'A';
> > > >>    }
> > > >>
> > > >>    printf("s.length      = %d\n",s.size());
> > > >> }
> > > >>
> > > >>        C        C++     C(64bit)    C++(64Bit)
> > > >> 500M  15.5     8.6     11.2        7.0
> > > >
> > > > What's the C timing; is that for my code?
> > > >
> > > > If so, it hasn't done too badly!
> > > 
> > > Yes.
> > 
> > Where's the source code for std::string?  I'd like to see how its
> > allocator works.
> 
> std::string is a typedef for std::basic_string<char>, which leaves Allocator
> unspecified. std::basic_string<charT, traits, Allocator> has a default value
> for Allocator of std::allocator<charT>. The features of std::allocator<T> are
> defined in section 20.8.9 of the C++ standard. In particular, the actual
> allocation of memory is done by calling ::operator new(std::size_t). That
> doesn't answer your question, but it does tell you which parts of the source
> code you should be looking for.

That's what I though.  Ultimately new() calls malloc().  I figure the
algorithm for the charT uses some sizeof operation to determine how
big of a buffer to allocate, which is then also optimized per platform.
I'm guessing though as I've never looked at the code, but it seems to
be a reasonable way it would be handled.

> Please don't ask me where to find those parts: I don't know any
> details at that level about any particular implementation of C++.

It's a deal. :-)

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#98082

Fromjameskuyper@verizon.net
Date2016-12-05 13:17 -0800
Message-ID<4ca5717e-ad34-41b8-994b-eafe8136071e@googlegroups.com>
In reply to#98061
On Monday, December 5, 2016 at 3:18:55 PM UTC-5, Rick C. Hodgin wrote:
> On Monday, December 5, 2016 at 3:13:01 PM UTC-5, james...@verizon.net wrote:
...
> > std::string is a typedef for std::basic_string<char>, which leaves Allocator
> > unspecified. std::basic_string<charT, traits, Allocator> has a default value
> > for Allocator of std::allocator<charT>. The features of std::allocator<T>
> > are defined in section 20.8.9 of the C++ standard. In particular, the actual
> > allocation of memory is done by calling ::operator new(std::size_t). That
> > doesn't answer your question, but it does tell you which parts of the source
> > code you should be looking for.
> 
> That's what I though.  Ultimately new() calls malloc().

That's purely an implementation-specific detail - the C++ standard neither
mandates nor prohibits it. It does, on the other hand, prohibit malloc() from
calling ::operator new() (20.8.13p3).

Section 3.7.4.3p2 of the C++ standard defines "safely derived pointers", as
including those returned by ::operator new(), but not those returned by
malloc() (that absence is pointed out in footnote 38, which might otherwise
have been though accidental). I read about this for the first time today, so
I'm not clear about the implications of that statement. The version of the C++
standard I'm most familiar with is C++98, and this was added at some later
time. 

> ...  I figure the
> algorithm for the charT uses some sizeof operation to determine how
> big of a buffer to allocate, which is then also optimized per platform.

Keep in mind that charT is char in this case, so sizeof(charT)==1.

[toc] | [prev] | [next] | [standalone]


#98087

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2016-12-05 13:29 -0800
Message-ID<6e21cf41-a464-426b-8bcb-af1a0981096e@googlegroups.com>
In reply to#98082
On Monday, December 5, 2016 at 4:17:44 PM UTC-5, james...@verizon.net wrote:
> On Monday, December 5, 2016 at 3:18:55 PM UTC-5, Rick C. Hodgin wrote:
> > On Monday, December 5, 2016 at 3:13:01 PM UTC-5, james...@verizon.net wrote:
> ...
> > > std::string is a typedef for std::basic_string<char>, which leaves Allocator
> > > unspecified. std::basic_string<charT, traits, Allocator> has a default value
> > > for Allocator of std::allocator<charT>. The features of std::allocator<T>
> > > are defined in section 20.8.9 of the C++ standard. In particular, the actual
> > > allocation of memory is done by calling ::operator new(std::size_t). That
> > > doesn't answer your question, but it does tell you which parts of the source
> > > code you should be looking for.
> > 
> > That's what I though.  Ultimately new() calls malloc().
> 
> That's purely an implementation-specific detail - the C++ standard neither
> mandates nor prohibits it. It does, on the other hand, prohibit malloc() from
> calling ::operator new() (20.8.13p3).

A-ha! :-)

> Section 3.7.4.3p2 of the C++ standard defines "safely derived pointers", as
> including those returned by ::operator new(), but not those returned by
> malloc() (that absence is pointed out in footnote 38, which might otherwise
> have been though accidental). I read about this for the first time today, so
> I'm not clear about the implications of that statement. The version of the C++
> standard I'm most familiar with is C++98, and this was added at some later
> time.

That does not correlate to my understanding of how C++ works.  I
presume, therefore, that my understanding is incorrect.  In my
understanding, both new() and malloc() would return pointers which
are equivalent, i.e. needing to be tested, and then able to be
used as needed.

> > ...  I figure the
> > algorithm for the charT uses some sizeof operation to determine how
> > big of a buffer to allocate, which is then also optimized per platform.
> 
> Keep in mind that charT is char in this case, so sizeof(charT)==1.

Correct.  I should've written, "I figure the algorithm for the charT
allocator (in this case) uses some sizeof operation to determine how
big of a buffer to allocate..."  I figured it was using a common
algorithm/template for the allocator, and would use some kind of
algorithm based on sizeof(charT) (or sizeof(whatever)) to determine
how much extra to allocate, rather than something generic like N *
sizeof(whatever).

Basically, I figure it's looking at how much lookahead it would need
for the algorithm peculiarities of its growth ability based on the
size of the thing it's allocating as by the template.

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#98107

Fromjameskuyper@verizon.net
Date2016-12-05 15:37 -0800
Message-ID<47a01ee6-3a2e-4d69-ab10-8053adf3528e@googlegroups.com>
In reply to#98087
On Monday, December 5, 2016 at 4:30:05 PM UTC-5, Rick C. Hodgin wrote:
> On Monday, December 5, 2016 at 4:17:44 PM UTC-5, james...@verizon.net wrote:
> > On Monday, December 5, 2016 at 3:18:55 PM UTC-5, Rick C. Hodgin wrote:
...
> > Section 3.7.4.3p2 of the C++ standard defines "safely derived pointers", as
> > including those returned by ::operator new(), but not those returned by
> > malloc() (that absence is pointed out in footnote 38, which might otherwise
> > have been though accidental). I read about this for the first time today, so
> > I'm not clear about the implications of that statement. The version of the C++
> > standard I'm most familiar with is C++98, and this was added at some later
> > time.
> 
> That does not correlate to my understanding of how C++ works.  I
> presume, therefore, that my understanding is incorrect.  In my
> understanding, both new() and malloc() would return pointers which
> are equivalent, i.e. needing to be tested, and then able to be
> used as needed.

Both pointers need to be tested - the differences between them fall under the "able to be used as needed" category. If you need to be able to call std::declare_reachable() or std::undeclare_reachable(), you can only do that with safely derived pointers (20.8.4). However, the memory allocated by members of the malloc() family is implicitly declared reachable (20.8.13p5), and remains reachable until free()d. Therefore, the real difference is that objects allocated by operator new() need NOT be declared reachable.
Again, I'm not sure of the implications of those facts, though a Note on 20.8.4p10 suggests it has something to do with garbage collection.

On an implementation with "strict pointer safety" requirements, operator delete() can only be passed safely derived pointer values (18.6.1p13, 18.6.2p12). This seems redundant to me, since the argument of operator delete() must either be null or a value allocated by calling operator new() (18.6.1p12, 18.6.2p11), and all such pointer values qualify as "safely derived pointers" (3.7.4.3p2).

The placement versions of operator delete() do NOT require that their argument be a value returned by operator new(), which makes sense, because those versions are only invoked when placement new results in a exception being thrown, which means placement new never got around to returning a value. However, on an implementation with "strict pointer safety", those functions still require their argument to be a "safely derived pointer". This implies that, when using such an implementation, you should not use placement new to construct an object in memory allocated by malloc() if the constructor might throw an exception?

There's clearly something I'm not understanding yet about C++'s pointer safety rules.
 
> > > ...  I figure the
> > > algorithm for the charT uses some sizeof operation to determine how
> > > big of a buffer to allocate, which is then also optimized per platform.
> > 
> > Keep in mind that charT is char in this case, so sizeof(charT)==1.
> 
> Correct.  I should've written, "I figure the algorithm for the charT
> allocator (in this case) uses some sizeof operation to determine how
> big of a buffer to allocate..."  I figured it was using a common
> algorithm/template for the allocator, and would use some kind of
> algorithm based on sizeof(charT) (or sizeof(whatever)) to determine
> how much extra to allocate, rather than something generic like N *
> sizeof(whatever).

The C++ standard library gives allocators and containers distinct roles to play. The allocator might allocate memory in blocks, and need to round the allocation up to an integer number of blocks. Other than that, I would expect logic such as you're suggesting to be part of the container code (in this case, std::string), rather than the allocator code. All of the capacity-related functions described in 21.4.4 of the C++ standard either affect how big the buffer needs to be, or need to report how big it is, so that shouldn't be left up to the allocator.

> Basically, I figure it's looking at how much lookahead it would need
> for the algorithm peculiarities of its growth ability based on the
> size of the thing it's allocating as by the template.

Imagine writing an allocator that can equally easily be used by std::vector<>, std::map<>, std::list<>, std::set<> and std::string<>. Would the lookahead strategy you're talking about be the same in each of those cases? If not, then it belongs in the container code, not the allocator code.

[toc] | [prev] | [next] | [standalone]


#98108

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2016-12-05 15:43 -0800
Message-ID<542aad23-30ac-4327-aacd-7b042e6eed4f@googlegroups.com>
In reply to#98107
On Monday, December 5, 2016 at 6:37:56 PM UTC-5, james...@verizon.net wrote:
> On Monday, December 5, 2016 at 4:30:05 PM UTC-5, Rick C. Hodgin wrote:
> > On Monday, December 5, 2016 at 4:17:44 PM UTC-5, james...@verizon.net > > > Keep in mind that charT is char in this case, so sizeof(charT)==1.
> > 
> > Correct.  I should've written, "I figure the algorithm for the charT
> > allocator (in this case) uses some sizeof operation to determine how
> > big of a buffer to allocate..."  I figured it was using a common
> > algorithm/template for the allocator, and would use some kind of
> > algorithm based on sizeof(charT) (or sizeof(whatever)) to determine
> > how much extra to allocate, rather than something generic like N *
> > sizeof(whatever).
> 
> The C++ standard library gives allocators and containers distinct roles to play. The allocator might allocate memory in blocks, and need to round the allocation up to an integer number of blocks. Other than that, I would expect logic such as you're suggesting to be part of the container code (in this case, std::string), rather than the allocator code. All of the capacity-related functions described in 21.4.4 of the C++ standard either affect how big the buffer needs to be, or need to report how big it is, so that shouldn't be left up to the allocator.

Very possible.  I didn't know the strict isolation was there.  Having
it in the container makes more sense, and relates back to what I was
saying to Bart previously, that C code does what it's instructed, and
it's up to the higher level algorithms to apply meaning to their use.

> > Basically, I figure it's looking at how much lookahead it would need
> > for the algorithm peculiarities of its growth ability based on the
> > size of the thing it's allocating as by the template.
> 
> Imagine writing an allocator that can equally easily be used by std::vector<>, std::map<>, std::list<>, std::set<> and std::string<>. Would the lookahead strategy you're talking about be the same in each of those cases? If not, then it belongs in the container code, not the allocator code.

Agreed.

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#98148

FromDavid Brown <david.brown@hesbynett.no>
Date2016-12-06 13:40 +0100
Message-ID<o26bhr$r3p$1@dont-email.me>
In reply to#98107
On 06/12/16 00:37, jameskuyper@verizon.net wrote:
> On Monday, December 5, 2016 at 4:30:05 PM UTC-5, Rick C. Hodgin
> wrote:
>> On Monday, December 5, 2016 at 4:17:44 PM UTC-5,
>> james...@verizon.net wrote:
>>> On Monday, December 5, 2016 at 3:18:55 PM UTC-5, Rick C. Hodgin
>>> wrote:
> ...
>>> Section 3.7.4.3p2 of the C++ standard defines "safely derived
>>> pointers", as including those returned by ::operator new(), but
>>> not those returned by malloc() (that absence is pointed out in
>>> footnote 38, which might otherwise have been though accidental).
>>> I read about this for the first time today, so I'm not clear
>>> about the implications of that statement. The version of the C++ 
>>> standard I'm most familiar with is C++98, and this was added at
>>> some later time.
>> 
>> That does not correlate to my understanding of how C++ works.  I 
>> presume, therefore, that my understanding is incorrect.  In my 
>> understanding, both new() and malloc() would return pointers which 
>> are equivalent, i.e. needing to be tested, and then able to be used
>> as needed.
> 
> Both pointers need to be tested - the differences between them fall
> under the "able to be used as needed" category. 

A pointer returned by "new" does not need to be tested (unless you are
using the nothrow new operator).  It either returns a valid object, or
it throws an exception.

> If you need to be
> able to call std::declare_reachable() or std::undeclare_reachable(),
> you can only do that with safely derived pointers (20.8.4). However,
> the memory allocated by members of the malloc() family is implicitly
> declared reachable (20.8.13p5), and remains reachable until free()d.
> Therefore, the real difference is that objects allocated by operator
> new() need NOT be declared reachable. Again, I'm not sure of the
> implications of those facts, though a Note on 20.8.4p10 suggests it
> has something to do with garbage collection.
> 
> On an implementation with "strict pointer safety" requirements,
> operator delete() can only be passed safely derived pointer values
> (18.6.1p13, 18.6.2p12). This seems redundant to me, since the
> argument of operator delete() must either be null or a value
> allocated by calling operator new() (18.6.1p12, 18.6.2p11), and all
> such pointer values qualify as "safely derived pointers"
> (3.7.4.3p2).

It does no harm to have a bit of redundancy in the C++ standard.  It is
even more complex than the C standard, and occasional redundant
repetition can save the reader manually cross-referencing these things.

[toc] | [prev] | [next] | [standalone]


#98178

From"James R. Kuyper" <jameskuyper@verizon.net>
Date2016-12-06 12:00 -0500
Message-ID<8e284338-d760-1b64-7efc-4c904f3462cd@verizon.net>
In reply to#98148
On 12/06/2016 07:40 AM, David Brown wrote:
> On 06/12/16 00:37, jameskuyper@verizon.net wrote:
>> On Monday, December 5, 2016 at 4:30:05 PM UTC-5, Rick C. Hodgin
>> wrote:
>>> On Monday, December 5, 2016 at 4:17:44 PM UTC-5,
>>> james...@verizon.net wrote:
>>>> On Monday, December 5, 2016 at 3:18:55 PM UTC-5, Rick C. Hodgin
>>>> wrote:
>> ...
>>>> Section 3.7.4.3p2 of the C++ standard defines "safely derived
>>>> pointers", as including those returned by ::operator new(), but
>>>> not those returned by malloc() (that absence is pointed out in
>>>> footnote 38, which might otherwise have been thought accidental).
>>>> I read about this for the first time today, so I'm not clear
>>>> about the implications of that statement. The version of the C++
>>>> standard I'm most familiar with is C++98, and this was added at
>>>> some later time.
>>>
>>> That does not correlate to my understanding of how C++ works.  I
>>> presume, therefore, that my understanding is incorrect.  In my
>>> understanding, both new() and malloc() would return pointers which
>>> are equivalent, i.e. needing to be tested, and then able to be used
>>> as needed.
>>
>> Both pointers need to be tested - the differences between them fall
>> under the "able to be used as needed" category.
>
> A pointer returned by "new" does not need to be tested (unless you are
> using the nothrow new operator).  It either returns a valid object, or

Since Rick mentioned testing it, I assumed he was referring to the 
nothrow version.

> it throws an exception.
>
>> If you need to be
>> able to call std::declare_reachable() or std::undeclare_reachable(),
>> you can only do that with safely derived pointers (20.8.4). However,
>> the memory allocated by members of the malloc() family is implicitly
>> declared reachable (20.8.13p5), and remains reachable until free()d.
>> Therefore, the real difference is that objects allocated by operator
>> new() need NOT be declared reachable. Again, I'm not sure of the
>> implications of those facts, though a Note on 20.8.4p10 suggests it
>> has something to do with garbage collection.
>>
>> On an implementation with "strict pointer safety" requirements,
>> operator delete() can only be passed safely derived pointer values
>> (18.6.1p13, 18.6.2p12). This seems redundant to me, since the
>> argument of operator delete() must either be null or a value
>> allocated by calling operator new() (18.6.1p12, 18.6.2p11), and all
>> such pointer values qualify as "safely derived pointers"
>> (3.7.4.3p2).
>
> It does no harm to have a bit of redundancy in the C++ standard.  It is
> even more complex than the C standard, and occasional redundant
> repetition can save the reader manually cross-referencing these things.

Yes, but this is a complicated redundancy, that doesn't save any 
cross-referncing. It naturally produces the suspicion that it might not 
be as redundant as it seems. Unless that is in fact the case, raising 
such suspicions is a bad idea. The C++ standard, after spending a 
half-page defining the term "safely derived pointer", uses it in only a 
small number of places, and most of those places are in reference to the 
argument of operator delete. What is the purpose of that term, if most 
of the uses of it are redundant? That's why I suspect that I'm not 
correctly understanding something.

[toc] | [prev] | [next] | [standalone]


#98183

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2016-12-06 10:09 -0800
Message-ID<e89b25a8-6779-4dca-9ab8-5fc9e80b6b41@googlegroups.com>
In reply to#98178
On Tuesday, December 6, 2016 at 12:00:26 PM UTC-5, James R. Kuyper wrote:
> On 12/06/2016 07:40 AM, David Brown wrote:
> > A pointer returned by "new" does not need to be tested (unless you are
> > using the nothrow new operator).  It either returns a valid object, or
> 
> Since Rick mentioned testing it, I assumed he was referring to the 
> nothrow version.

Nope.  I thought you had to test pointers returned by new() in C++.
My ignorance.  My mistake.

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#98189

FromJerry Stuckle <jstucklex@attglobal.net>
Date2016-12-06 13:33 -0500
Message-ID<o2706q$9hu$1@jstuckle.eternal-september.org>
In reply to#98183
On 12/6/2016 1:09 PM, Rick C. Hodgin wrote:
> On Tuesday, December 6, 2016 at 12:00:26 PM UTC-5, James R. Kuyper wrote:
>> On 12/06/2016 07:40 AM, David Brown wrote:
>>> A pointer returned by "new" does not need to be tested (unless you are
>>> using the nothrow new operator).  It either returns a valid object, or
>>
>> Since Rick mentioned testing it, I assumed he was referring to the 
>> nothrow version.
> 
> Nope.  I thought you had to test pointers returned by new() in C++.
> My ignorance.  My mistake.
> 
> Best regards,
> Rick C. Hodgin
> 

In earlier versions of C++, you did - new either returned a pointer to
the new object or NULL, like in C.

The standard changed such that new now throws an exception if the object
can't be built, which is actually more useful.  Out of memory may not be
the only reason the object can't be built; for instance the constructor
may find a problem and throw an exception.

But this could cause problems with previous versions of programs, which
weren't expecting new to throw an exception.  Therefore compilers have
an means of disabling the exception and return NULL instead for
compatibility reasons.

-- 
==================
Remove the "x" from my email address
Jerry Stuckle
jstucklex@attglobal.net
==================

[toc] | [prev] | [next] | [standalone]


#98206

FromDavid Brown <david.brown@hesbynett.no>
Date2016-12-06 21:24 +0100
Message-ID<o276o3$1h0$1@dont-email.me>
In reply to#98183
On 06/12/16 19:09, Rick C. Hodgin wrote:
> On Tuesday, December 6, 2016 at 12:00:26 PM UTC-5, James R. Kuyper wrote:
>> On 12/06/2016 07:40 AM, David Brown wrote:
>>> A pointer returned by "new" does not need to be tested (unless you are
>>> using the nothrow new operator).  It either returns a valid object, or
>>
>> Since Rick mentioned testing it, I assumed he was referring to the
>> nothrow version.
>
> Nope.  I thought you had to test pointers returned by new() in C++.
> My ignorance.  My mistake.
>

We are all here to learn.

And you /do/ have to test the return of new() if you use the nothrow 
version, or if you have exceptions disabled.  If you are using your C++ 
compiler as a sort of C with slightly stronger checking, then you might 
want to disable exceptions (I presume MSVC has a way to do this).  Of 
course, if you are using it basically as a sort-of C compiler then you 
would not be using "new" ...


[toc] | [prev] | [next] | [standalone]


#98207

From"Rick C. Hodgin" <rick.c.hodgin@gmail.com>
Date2016-12-06 12:56 -0800
Message-ID<8419493e-21c3-4f78-bc5c-7007411c6e4a@googlegroups.com>
In reply to#98206
On Tuesday, December 6, 2016 at 3:25:04 PM UTC-5, David Brown wrote:
> On 06/12/16 19:09, Rick C. Hodgin wrote:
> > On Tuesday, December 6, 2016 at 12:00:26 PM UTC-5, James R. Kuyper wrote:
> >> On 12/06/2016 07:40 AM, David Brown wrote:
> >>> A pointer returned by "new" does not need to be tested (unless you are
> >>> using the nothrow new operator).  It either returns a valid object, or
> >>
> >> Since Rick mentioned testing it, I assumed he was referring to the
> >> nothrow version.
> >
> > Nope.  I thought you had to test pointers returned by new() in C++.
> > My ignorance.  My mistake.
> 
> We are all here to learn.
> 
> And you /do/ have to test the return of new() if you use the nothrow 
> version, or if you have exceptions disabled.  If you are using your C++ 
> compiler as a sort of C with slightly stronger checking, then you might 
> want to disable exceptions (I presume MSVC has a way to do this).  Of 
> course, if you are using it basically as a sort-of C compiler then you 
> would not be using "new" ...

I do typically disable exceptions in my projects anyway, even in those
that use C++ (I have a handful where I use classes instead of structs).

The only times I can remember needing to enable them are when I've had
some runtime error that seemed like it was the result of a library or
OS bug, something I wasn't able to find the cause of, and I had to have
a way to catch it at runtime without it halting the application.

I'm pretty sure I've always tested pointers that have been allocated,
unless it's some kind of code I use for debugging where I'll be in the
debugger if it fails, and it will catch it right there anyway.

Best regards,
Rick C. Hodgin

[toc] | [prev] | [next] | [standalone]


#98063

FromKeith Thompson <kst-u@mib.org>
Date2016-12-05 12:22 -0800
Message-ID<lnbmwq3z39.fsf@kst-u.example.com>
In reply to#98042
Ian Collins <ian-news@hotmail.com> writes:
[...]
>    printf("s.length      = %d\n",s.size());

Doesn't s.size() return a size_t result rather than int?  (Normally in
C++ you'd use `std::cout << ...`, which neatly avoids the issue.)

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#98023

Fromsupercat@casperkitty.com
Date2016-12-05 08:36 -0800
Message-ID<949ba4ee-4184-4cf0-954a-cfb77bc09553@googlegroups.com>
In reply to#98021
On Monday, December 5, 2016 at 10:28:31 AM UTC-6, Bart wrote:
> void appendchar(Cstr* S, char c){
> 
>     if (S->length==0) {
>        S->length=1;
>        S->str=malloc(2);
>        *(S->str)=c;
>        *(S->str+1)=0;
>     }
>     else {
>        ++S->length;
>        S->str=realloc(S->str,S->length+1);
>        *(S->str+S->length-1)=c;
>        *(S->str+S->length)=0;
>     }
> }

This code hints at a big reason why I suggested that strings should keep
track of both buffer size and string length.  If those are tracked
separately and code needs to expand a string, it can expand it to either
the required size or some multiple (possibly fractional) of its previous
length (e.g. 1.25x, 1.5x or 2x).  The same issue is observable in Java and
.NET if code uses their String type rather than StringBuilder [the former
will perform a new allocation with each append; the latter will perform
roughly lg(N) allocations when building a string of size N].

[toc] | [prev] | [next] | [standalone]


#98027

FromBartC <bc@freeuk.com>
Date2016-12-05 17:31 +0000
Message-ID<o2487j$f4c$1@dont-email.me>
In reply to#98023
On 05/12/2016 16:36, supercat@casperkitty.com wrote:
> On Monday, December 5, 2016 at 10:28:31 AM UTC-6, Bart wrote:
>> void appendchar(Cstr* S, char c){
>>
>>     if (S->length==0) {
>>        S->length=1;
>>        S->str=malloc(2);
>>        *(S->str)=c;
>>        *(S->str+1)=0;
>>     }
>>     else {
>>        ++S->length;
>>        S->str=realloc(S->str,S->length+1);
>>        *(S->str+S->length-1)=c;
>>        *(S->str+S->length)=0;
>>     }
>> }
>
> This code hints at a big reason why I suggested that strings should keep
> track of both buffer size and string length.  If those are tracked
> separately and code needs to expand a string, it can expand it to either
> the required size or some multiple (possibly fractional) of its previous
> length (e.g. 1.25x, 1.5x or 2x).

Presumably malloc/realloc don't do any over-allocation of their own (not 
significant anyway apart perhaps from rounding).

This is why I normally have to wrap extra memory management around 
malloc (I don't use realloc much).

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


#98075

FromDavid Brown <david.brown@hesbynett.no>
Date2016-12-05 22:07 +0100
Message-ID<o24kst$ar$1@dont-email.me>
In reply to#98027
On 05/12/16 18:31, BartC wrote:
> On 05/12/2016 16:36, supercat@casperkitty.com wrote:
>> On Monday, December 5, 2016 at 10:28:31 AM UTC-6, Bart wrote:
>>> void appendchar(Cstr* S, char c){
>>>
>>>     if (S->length==0) {
>>>        S->length=1;
>>>        S->str=malloc(2);
>>>        *(S->str)=c;
>>>        *(S->str+1)=0;
>>>     }
>>>     else {
>>>        ++S->length;
>>>        S->str=realloc(S->str,S->length+1);
>>>        *(S->str+S->length-1)=c;
>>>        *(S->str+S->length)=0;
>>>     }
>>> }
>>
>> This code hints at a big reason why I suggested that strings should keep
>> track of both buffer size and string length.  If those are tracked
>> separately and code needs to expand a string, it can expand it to either
>> the required size or some multiple (possibly fractional) of its previous
>> length (e.g. 1.25x, 1.5x or 2x).
>
> Presumably malloc/realloc don't do any over-allocation of their own (not
> significant anyway apart perhaps from rounding).
>

It is not uncommon for malloc to over-allocate to keep everything 
aligned to cache line sizes.  But you don't get easy access to that 
extra memory - keeping the buffer size independent from the string 
length is the only way to go.

> This is why I normally have to wrap extra memory management around
> malloc (I don't use realloc much).
>

[toc] | [prev] | [next] | [standalone]


#98080

FromIan Collins <ian-news@hotmail.com>
Date2016-12-06 10:14 +1300
Message-ID<eam3mjFkmtmU6@mid.individual.net>
In reply to#98023
On 12/ 6/16 05:36 AM, supercat@casperkitty.com wrote:
> On Monday, December 5, 2016 at 10:28:31 AM UTC-6, Bart wrote:
>> void appendchar(Cstr* S, char c){
>>
>>      if (S->length==0) {
>>         S->length=1;
>>         S->str=malloc(2);
>>         *(S->str)=c;
>>         *(S->str+1)=0;
>>      }
>>      else {
>>         ++S->length;
>>         S->str=realloc(S->str,S->length+1);
>>         *(S->str+S->length-1)=c;
>>         *(S->str+S->length)=0;
>>      }
>> }
>
> This code hints at a big reason why I suggested that strings should keep
> track of both buffer size and string length.  If those are tracked
> separately and code needs to expand a string, it can expand it to either
> the required size or some multiple (possibly fractional) of its previous
> length (e.g. 1.25x, 1.5x or 2x).  The same issue is observable in Java and
> .NET if code uses their String type rather than StringBuilder [the former
> will perform a new allocation with each append; the latter will perform
> roughly lg(N) allocations when building a string of size N].

This is certainly one case where adding a little complexity 
significantly improves performance.  If you add a capacity to the 
string, the resulting performance jump is dramatic:

typedef struct {
   char* str;
   uint32_t length;
   uint32_t capacity;
   uint32_t delta;
} Cstr;

void appendchar(Cstr* S, char c){

     if (S->length==0) {
        S->length=1;
        S->str=malloc(S->delta);
        S->capacity += S->delta;
        S->delta = (S->delta*3)/2;
     }
     else {
        if( ++S->length >= S->capacity )
        {
          S->capacity += S->delta;
          S->str=realloc(S->str,S->capacity);
          //printf("%d %d\n",S->length,S->capacity);
          S->delta = (S->delta*3)/2;
        }
     }
     *(S->str+S->length-1)=c;
     *(S->str+S->length)=0;
}

Runs in 1.1 seconds for 500M appends.  If you remove the delta and 
simply grow in 32 byte steps, it runs in 1.6 seconds.

-- 
Ian

[toc] | [prev] | [next] | [standalone]


#98098

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2016-12-05 22:11 +0000
Message-ID<87shq2gh64.fsf@bsb.me.uk>
In reply to#98021
BartC <bc@freeuk.com> writes:

> On 05/12/2016 15:38, Rick C. Hodgin wrote:
>
>> C is already much faster than other languages.  It's why I use it.
>
> Take this simple implementation of a counted string type and character
> append routine (see below).
>
> To append 'A' 10 million times starting with an empty string took
> about 13 seconds (gcc -O3, Windows CRT).
>
> My little *interpreted* language took under 0.2 seconds.
>
> Then I tried 100 million appends. My language took 1.7 seconds (ten
> times as long). As for the C, I started it around ten minutes ago, and
> it's still running...
>
> Yes, the C can be nearly as fast, with enough effort. But it's about
> algorithms rather than language.

Yes, algorithms and data structures.  The usual method is to store the
size and multiply it by a constant factor when reallocating.  When you
do that, it's also faster to zero the new store in one go rather than
writing a null byte on every append.  Here's that version with added
error-checking:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
   char* str;
   int length;
   int size;
} Cstr;

int appendchar(Cstr *s, char c)
{
     if (s->length + 1 >= s->size) {
          int nsz = s->size * 3 / 2 + 16;
          char *nstr = realloc(s->str, nsz);
          if (!nstr) return 0;
          memset(nstr + s->size, 0, nsz - s->size);
          s->size = nsz;
          s->str = nstr;
     }
     s->str[s->length++] = c;
     return 1;
}

int main(int argc, char **argv)
{
     int len = argc > 1 ? atoi(argv[1]) : 500*1000*1000;
     Cstr s = {0};

     for (int i = 0; i < len && appendchar(&s, 'A'); ++i);

     printf("s.length      = %d\n", s.length);
     printf("strlen(s.str) = %zu\n", strlen(s.str));
}

<snip>
-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#98114

FromBartC <bc@freeuk.com>
Date2016-12-06 02:13 +0000
Message-ID<o256p9$rek$1@dont-email.me>
In reply to#98098
On 05/12/2016 22:11, Ben Bacarisse wrote:
> BartC <bc@freeuk.com> writes:

>> Take this simple implementation of a counted string type and character
>> append routine (see below).
>>
>> To append 'A' 10 million times starting with an empty string took
>> about 13 seconds (gcc -O3, Windows CRT).
>>
>> My little *interpreted* language took under 0.2 seconds.

>> Yes, the C can be nearly as fast, with enough effort. But it's about
>> algorithms rather than language.

> Yes, algorithms and data structures.  The usual method is to store the
> size and multiply it by a constant factor when reallocating.  When you
> do that, it's also faster to zero the new store in one go rather than
> writing a null byte on every append.  Here's that version with added
> error-checking:
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> typedef struct {
>    char* str;
>    int length;
>    int size;
> } Cstr;
>
> int appendchar(Cstr *s, char c)
> {
>      if (s->length + 1 >= s->size) {
>           int nsz = s->size * 3 / 2 + 16;
>           char *nstr = realloc(s->str, nsz);
>           if (!nstr) return 0;
>           memset(nstr + s->size, 0, nsz - s->size);
>           s->size = nsz;
>           s->str = nstr;
>      }
>      s->str[s->length++] = c;
>      return 1;
> }
>
> int main(int argc, char **argv)
> {
>      int len = argc > 1 ? atoi(argv[1]) : 500*1000*1000;
>      Cstr s = {0};
>
>      for (int i = 0; i < len && appendchar(&s, 'A'); ++i);
>
>      printf("s.length      = %d\n", s.length);
>      printf("strlen(s.str) = %zu\n", strlen(s.str));
> }

I ran your code with these results for 500M (on Windows):

              32-bit      64-bit
gcc -O3      2.2         1.5       seconds
mid-Cs -O   ~4.5         3.5       [Pelles C, lccwin, DMC]
Tiny C       7.4         6.5
MSVC /O2     1.8         --        [2008]
gcc -O0      --          4.8

Interpreted  --          8.4       [Fastest]

I'm not sure why 64 bits makes such a difference (usually it slows it 
down!).

(I took out the memset, and the strlen call, as the interpreted version 
doesn't use a zero terminator.)

So with dedicated allocation code, the C can easily beat the interpreted 
program. But the latter still isn't bad considering it also has to take 
care of decoding four byte-code instructions, do a dynamic type dispatch 
and deal with reference counts for each iteration! Also it has to use 
the same memory allocator as other objects, not a dedicated one. 
However, it uses some ASM code to get this speed.)

-- 
Bartc

[toc] | [prev] | [next] | [standalone]


Page 4 of 6 — ← Prev page 1 2 3 [4] 5 6  Next page →

Back to top | Article view | comp.lang.c


csiph-web