From my test yesterday night I got the impression 8 times slower than plain indexing like s[i] = i when compiled with -d:release. For a preallocated seq. My estimation was only a factor 3.
So i just looked at the C code:
const
M = 1e7.int
type
MySeq = seq[int]
var
s: MySeq = newSeq[int](M)
proc fill_seq(s: var MySeq) =
for i in 0..<M:
s.add(i)
#s[i] = i
fill_seq(s)
{ while (1) { if (!(res_92118 <= HEX3Atmp_92116)) goto LA4; x_92112 = res_92118; i_92096 = x_92112; (*s) = (Myseq92006*) incrSeqV2(&((*s))->Sup, sizeof(NI)); (*s)->data[(*s)->Sup.len] = i_92096; ++(*s)->Sup.len; res_92118 += ((NI) 1); } LA4: ; }
Is my impression correct that for each add incrSeqV2() is called to increase seq size?
Oh -- I have the feeling that I missunderstand behaviour.
My intent was to preallocate memory for seq, but start adding at position zero. But now I have the feeling that add() adds indeed at the end of the preallocated buffer, so my add loop starts at position 1E7? Can I preallocate buffer but start at zero with add?
[EDIT]
Yes indeed, I have 1E7 zeros and then add my ints :-( I have not noticed that before because I generally started with an empty seq of size zero. Sequences are convenient of course, but when add() is 8 times slower than indexing, then it is good to know that.
To answer my own questions, seq.setlen(0) is available for adding really at the beginning when seq was allocated with initial size greater zero. That may be useful when we know the minimal resulting size in advance, but it gives not much more performance for my test.
Second, C++ has vectors, and I did a short test:
#include <vector> int main () { std::vector<int> myvector; int i; i = 0; while (i++ < 10000000) { myvector.push_back (i); }; return 0; }
For my test that is 2 to 3 times faster than seq.add(), so improvements may be possible. I also tested with a seq defined not globally, but in a proc, that made not much difference. Generally performance of seq.add() may be not of great importance in real programs, but one may be tempted to avoid it when one knows that it is much slower than index access.
Yes. I had that in my mind, but did not test, my feeling was that that would not really matter. Will test now...
[EDIT]
Yes, C with int64_64 is indeed slower than with int32_t, maybe 70% slower But for my box time is only halve that of seq.add() stll. Both with gcc 5.3 and -O3.
But indeed that is not really bad, and other seq operations are more important. :-)
[EDIT2]
But seq.setlen(0) gives me nearly a factor 2 in this example, so Nim and C++ have exactly the same performance! Great.
const
M = 1E7.int
type
MySeq = seq[int]
proc fill_seq(s: var MySeq) =
for i in 0..<M:
s.add(i)
proc main =
var
s: MySeq = newSeq[int](M)
s.setlen(0)
fill_seq(s)
main()