Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

"Life sucks, but death doesn't put out at all...." -- Thomas J. Kopp


devel / comp.lang.c / Re: Why does C allow structs to have a tag?

Re: Why does C allow structs to have a tag?

<sf1i29$jdp$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=17924&group=comp.lang.c#17924

  copy link   Newsgroups: comp.lang.c
Path: i2pn2.org!i2pn.org!eternal-september.org!reader02.eternal-september.org!.POSTED!not-for-mail
From: bc...@freeuk.com (Bart)
Newsgroups: comp.lang.c
Subject: Re: Why does C allow structs to have a tag?
Date: Wed, 11 Aug 2021 23:13:21 +0100
Organization: A noiseless patient Spider
Lines: 279
Message-ID: <sf1i29$jdp$1@dont-email.me>
References: <s9iea5$n5c$1@dont-email.me> <sembba$oul$1@dont-email.me>
<CrQPI.669$bS5.239@fx21.iad> <seoqf4$pj7$1@dont-email.me>
<87czqnlp2m.fsf@bsb.me.uk> <WFWPI.1865$un2.1665@fx04.iad>
<FiCQI.401$uk4.259@fx20.iad> <poCQI.37363$EF2.25668@fx47.iad>
<VNCQI.5685$Ug5.514@fx24.iad> <seuu75$il3$1@dont-email.me>
<TEEQI.5686$Ug5.143@fx24.iad> <GCQQI.17254$lK.16624@fx41.iad>
<5d8700fd-6ba7-4c72-ae2f-1d4ea91fe823n@googlegroups.com>
<PHRQI.5464$xY.2133@fx05.iad> <sf0re4$v91$1@dont-email.me>
<sf1e9g$14$1@z-news.wcss.wroc.pl>
Mime-Version: 1.0
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Wed, 11 Aug 2021 22:13:29 -0000 (UTC)
Injection-Info: reader02.eternal-september.org; posting-host="99fe37e4e79e4f9d568828aa5779e349";
logging-data="19897"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1/NgUtqezpdQqbDBVTwTYfGO02xZM0RDN8="
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:78.0) Gecko/20100101
Thunderbird/78.11.0
Cancel-Lock: sha1:hN6tgGy60Ryj2YzfTcmCpjJTE0s=
In-Reply-To: <sf1e9g$14$1@z-news.wcss.wroc.pl>
X-Antivirus-Status: Clean
Content-Language: en-GB
X-Antivirus: AVG (VPS 210811-2, 11/8/2021), Outbound message
 by: Bart - Wed, 11 Aug 2021 22:13 UTC

On 11/08/2021 22:09, antispam@math.uni.wroc.pl wrote:
> Bart <bc@freeuk.com> wrote:
>> On 11/08/2021 16:06, Scott Lurndal wrote:
>>> Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:
>>>> On Wednesday, 11 August 2021 at 14:52:54 UTC+1, Scott Lurndal wrote:
>>>>>
>>>>> strcat is almost never the right interface to use. It needs
>>>>> to scan the entire string to find the terminal nul-byte before
>>>>> appending. As the string gets longer, each strcat takes longer
>>>>> than the one before.
>>>>>
>>>>> Just keep a pointer to the next element and increment the
>>>>> pointer each time you add a new element.
>>>>>
>>>> Most strings are short. Building up a url with strcat is not going to
>>>> stress a 3GHz machine. If the strings become huge then, yes, you
>>>> need to look at more efficient ways of concatenating them.
>>>
>>> Building it with snprintf() will be far more flexible and efficient.
>>>
>>> Every cycle matters.
>>>
>>
>>
>> Start with this:
>>
>> char str[100];
>> char* s;
>>
>> Then a loop like this (all unoptimised code to stop it being optimised
>> out of existence):
>
> Again this nonsense with unoptimized benchmarks. Write your
> benchmark to realisticaly simulate actual load. If you
> have real code and compiler optimizes part of it out of
> existence, then this is good things, means that task
> can be done simpler/faster than what programmer expected.

No it is a bad thing. You want such a test to tell you a general thing:
is strcat to concatenate multiple short strings generally better than
multiple calls to sprintf?

That it can optimise both away in this specific, silly benchmark tells
you nothing.

See my reply to David Brown a few minutes ago where I did enable
optimisation on my compilers, with a revised test.

>> for (int i=0; i<10000000; ++i) {
>> strcpy(str,"one ");
>> strcat(str,"two ");
>> strcat(str,"three ");
>> strcat(str,"four ");
>> strcat(str,"five");
>> }
>> puts(str);
>>
>>
>> took 1 second (on my Windows PC running tcc). If use sprintf():
>>
>> for (int i=0; i<10000000; ++i) {
>> s=str;
>> s+=sprintf(s,"%s","one ");
>> s+=sprintf(s,"%s","two ");
>> s+=sprintf(s,"%s","three ");
>> s+=sprintf(s,"%s","four ");
>> sprintf(s,"%s","five");
>> }
>> puts(s);
>>
>> then it takes 5.5 seconds. With snprintf() as you suggest, it takes 6.1
>> seconds. I thought you said every cycle matters?
>
> On may machine, using cc -O2 I get:
>
> time ./b2
> five
>
> real 0m0.049s
> user 0m0.044s
> sys 0m0.004s
>
> Assembler output for the crucial part is:
>
> movl $10000000, %eax #, ivtmp_1
> .p2align 4,,10
> .p2align 3
> .L2:
> movl $8293, %ecx #,
> movl $32, %esi #,
> subl $1, %eax #, ivtmp_1
> movw %si, 18+str(%rip) #, MEM[(void *)&str + 14B]
> movl $543518319, str(%rip) #, MEM[(void *)&str]
> movl $544175988, 4+str(%rip) #, MEM[(void *)&str + 4B]
> movl $1701996660, 8+str(%rip) #, MEM[(void *)&str + 8B]
> movw %cx, 12+str(%rip) #, MEM[(void *)&str + 8B]
> movl $1920298854, 14+str(%rip) #, MEM[(void *)&str + 14B]
> movq %rdx, s(%rip) # tmp98, s
> movl $1702259046, 19+str(%rip) #, MEM[(void *)&str + 19B]
> movb $0, 23+str(%rip) #, MEM[(void *)&str + 19B]
> jne .L2 #,
> leaq 19+str(%rip), %rdi #,
> call puts@PLT

This is what I get for the c.c module of my last past, with gcc -O3 -S
(comments and other noise deleted):

printf:
push r12 #
push rbx #
sub rsp, 56 #,
lea rbx, 88[rsp] # tmp86,
mov QWORD PTR 88[rsp], rdx #,
mov r12, rcx # __format, tmp89
mov ecx, 1 #,
mov QWORD PTR 96[rsp], r8 #,
mov QWORD PTR 104[rsp], r9 #,
mov QWORD PTR 40[rsp], rbx # MEM[(char * *)&__local_argv], tmp86
call [QWORD PTR __imp___acrt_iob_func[rip]] #
mov r8, rbx #, tmp86
mov rdx, r12 #, __format
mov rcx, rax # _2, tmp90
call __mingw_vfprintf #
add rsp, 56 #,
pop rbx #
pop r12 #
ret
..LC0:
sprintf.constprop.0:
sub rsp, 56 #,
lea rdx, .LC0[rip] #,
lea rcx, str[rip] #,
mov QWORD PTR 80[rsp], r8 #,
lea r8, 80[rsp] # tmp86,
mov QWORD PTR 88[rsp], r9 #,
mov QWORD PTR 40[rsp], r8 # MEM[(char * *)&__local_argv], tmp86
call __mingw_vsprintf #
add rsp, 56 #,
ret
sprintf.constprop.1:
sub rsp, 56 #,
lea rdx, .LC0[rip] #,
mov QWORD PTR 80[rsp], r8 #,
lea r8, 80[rsp] # tmp86,
mov QWORD PTR 88[rsp], r9 #,
mov QWORD PTR 40[rsp], r8 # MEM[(char * *)&__local_argv], tmp86
call __mingw_vsprintf #
add rsp, 56 #,
ret
..LC1:
.ascii "%d\12\0"
..LC2:
.ascii "time1 %d\12\0"
..LC3:
.ascii "time2 %d\12\0"
..LC4:
.ascii "\0"
.section .text.startup,"x"
main:
push r13 #
push r12 #
push rbp #
push rdi #
push rsi #
push rbx #
sub rsp, 40 #,
mov esi, 1000000 # ivtmp_24,
lea rbx, str[rip] # tmp134,
call __main #
call clock #
mov edi, eax # t, tmp135
..L6:
call getstr #
mov rcx, rbx #, tmp134
mov rdx, rax # _1, tmp136
call strcpy #
call getstr #
mov rcx, rbx #, tmp134
mov rdx, rax # _2, tmp137
call strcat #
call getstr #
mov rcx, rbx #, tmp134
mov rdx, rax # _3, tmp138
call strcat #
call getstr #
mov rcx, rbx #, tmp134
mov rdx, rax # _4, tmp139
call strcat #
call getstr #
mov rcx, rbx #, tmp134
mov rdx, rax # _5, tmp140
call strcat #
sub esi, 1 # ivtmp_24,
jne .L6 #,
lea rcx, str[rip] #,
lea rbp, str[rip] # tmp131,
call puts #
lea rcx, str[rip] #,
lea rsi, .LC0[rip] # tmp132,
call strlen #
lea rcx, .LC1[rip] #,
mov rdx, rax # tmp118, tmp141
call printf #
call clock #
lea rcx, .LC2[rip] #,
sub eax, edi # tmp142, t
mov edi, 1000000 # ivtmp_23,
mov edx, eax # tmp120, tmp142
call printf #
call clock #
mov r13d, eax # t, tmp143
..L7:
call getstr #
mov rdx, rsi #, tmp132
mov rcx, rbp #, tmp131
mov r8, rax # tmp144,
call sprintf.constprop.0 #
movsx rbx, eax # _43, tmp145
call getstr #
add rbx, rbp # s, tmp131
mov rdx, rsi #, tmp132
mov rcx, rbx #, s
mov r8, rax # tmp146,
call sprintf.constprop.1 #
cdqe
add rbx, rax # s, _47
call getstr #
mov rcx, rbx #, s
mov rdx, rsi #, tmp132
mov r8, rax # tmp148,
call sprintf.constprop.1 #
cdqe
add rbx, rax # s, _51
call getstr #
mov rdx, rsi #, tmp132
mov rcx, rbx #, s
mov r8, rax # tmp150,
call sprintf.constprop.1 #
movsx r12, eax # _55, tmp151
call getstr #
add r12, rbx # s, s
mov rdx, rsi #, tmp132
mov r8, rax # tmp152,
mov rcx, r12 #, s
call sprintf.constprop.1 #
sub edi, 1 # ivtmp_23,
jne .L7 #,
lea rcx, str[rip] #,
call puts #
lea rcx, str[rip] #,
call strlen #
lea rcx, .LC1[rip] #,
mov rdx, rax # tmp127, tmp153
call printf #
call clock #
lea rcx, .LC3[rip] #,
sub eax, r13d # tmp154, t
mov edx, eax # tmp129, tmp154
call printf #
lea rcx, .LC4[rip] #,
call puts #
xor eax, eax #
add rsp, 40 #,
pop rbx #
pop rsi #
pop rdi #
pop rbp #
pop r12 #
pop r13 #
ret
str:
.space 100000
.ident "GCC: (tdm64-1) 10.3.0"

I guess this is again either all my fault for not knowing what options I
need to make the code as sweet as yours, or Windows' for being such a
crap OS, or both.

SubjectRepliesAuthor
o Why does C allow structs to have a tag?

By: James Harris on Sun, 6 Jun 2021

391James Harris
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor