469,266 Members | 1,951 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,266 developers. It's quick & easy.

For vs. For Each

Is there a performance difference between this:

\\\
Dim i As Integer
For i = 0 to myObject.Controls.Count - 1
myObject.Controls(i) = ...
Next
///

and this:

\\\
Dim ctl As Control
For Each ctl In myObject.Controls
ctl = ...
Next
///

Or is For Each just "prettier"?

Thanks,

Eric
Nov 21 '05
65 3073
Hi,

I may have misunderstood what was said, but at a recent Tech ED 2004 seminar
(in NZ) we were told that FOREACH is not a good idea on collections
containing primitive data types (i.e integers etc).
Apparently this is because it causing a lot of unnecesary "boxing"
(converting the primitive data type into an object) and "unboxing" (the
reverse). Apparently if you have a collection of ints you should use for.
Why anyone would foreach through a collection of ints I don't know.

Apparently this is a bigger problem when developing with the compact .net
framework (for mobile devices), because this sort of application normally
runs on devices with smaller amounts of memory available. If too much
boxing/unboxing goes on the garbage collector then has a lot of work to do
and runs quite often, slowing down the app.

In a desktop environment it's presumably less of a problem.
"an*******@discussions.microsoft.com" wrote:
Is there a performance difference between this:

\\\
Dim i As Integer
For i = 0 to myObject.Controls.Count - 1
myObject.Controls(i) = ...
Next
///

and this:

\\\
Dim ctl As Control
For Each ctl In myObject.Controls
ctl = ...
Next
///

Or is For Each just "prettier"?

Thanks,

Eric

Nov 21 '05 #51
Troy <Tr**@discussions.microsoft.com> wrote:
I may have misunderstood what was said, but at a recent Tech ED 2004 seminar
(in NZ) we were told that FOREACH is not a good idea on collections
containing primitive data types (i.e integers etc).


I don't believe that's not generally true. If the collection already
has the data in boxed form, it needs to be unboxed anyway. If you're
dealing with an array, no boxing needs to occur.

The only time I can see it being true is with a collection which does
actually have a strongly-typed interface to it and stores the ints
without boxing, where an iterator would need to box. I think that's a
relatively rare situation, myself.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 21 '05 #52
On 2004-08-21, Jon Skeet [ C# MVP ] <sk***@pobox.com> wrote:
Troy <Tr**@discussions.microsoft.com> wrote:
I may have misunderstood what was said, but at a recent Tech ED 2004 seminar
(in NZ) we were told that FOREACH is not a good idea on collections
containing primitive data types (i.e integers etc).
I don't believe that's not generally true.


I'm not sure I'm parsing that correctly.
If the collection already
has the data in boxed form, it needs to be unboxed anyway. If you're
dealing with an array, no boxing needs to occur.

The only time I can see it being true is with a collection which does
actually have a strongly-typed interface to it and stores the ints
without boxing, where an iterator would need to box. I think that's a
relatively rare situation, myself.


My first thought was "Wouldn't that be the case with any array of value
type?"

But, a few seconds later...

OK, strike that, I'm wrong of course. I just glanced at the IL and using
foreach on an array of int doesn't call GetEnumerator, it inlines the
loop instead, avoiding any boxing. That's interesting.

Do you know if language matters here? Is this an optimization of the C#
compiler, or something inherent to the CLR?

Nov 21 '05 #53
David <df*****@woofix.local.dom> wrote:
On 2004-08-21, Jon Skeet [ C# MVP ] <sk***@pobox.com> wrote:
Troy <Tr**@discussions.microsoft.com> wrote:
I may have misunderstood what was said, but at a recent Tech ED 2004 seminar
(in NZ) we were told that FOREACH is not a good idea on collections
containing primitive data types (i.e integers etc).
I don't believe that's not generally true.


I'm not sure I'm parsing that correctly.


Nah, I just made a typo. It should have been "I'm not sure that's
generally true."
If the collection already
has the data in boxed form, it needs to be unboxed anyway. If you're
dealing with an array, no boxing needs to occur.

The only time I can see it being true is with a collection which does
actually have a strongly-typed interface to it and stores the ints
without boxing, where an iterator would need to box. I think that's a
relatively rare situation, myself.


My first thought was "Wouldn't that be the case with any array of value
type?"

But, a few seconds later...

OK, strike that, I'm wrong of course. I just glanced at the IL and using
foreach on an array of int doesn't call GetEnumerator, it inlines the
loop instead, avoiding any boxing. That's interesting.


It's pretty necessary, to be honest - the performance penalties
otherwise would be awful, and completely unnecessary.
Do you know if language matters here? Is this an optimization of the C#
compiler, or something inherent to the CLR?


It's the C# compiler - the CLR itself doesn't know about foreach at
all.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 21 '05 #54
John,

Also, I highly disagree that the for-construct is faster than
foreach-construct. That is only true when you are talking about ARRAY
collection types.
<<

What list based collections support interger based indexers that you
could use a 'for' loop on?

Granted the underlying implementation for any .NET 1.1 collection is
generally hidden behind an interface but if you look at the standard
collections ( including namespace specialized ) any collection that's
specifically list based only offers enumerators and can only be accessed
with 'foreach'.

And because the actual implementation hidden there's really no way to
provide a general answer unless it's comming from someone that knows the
inside of the CLR, the the various compilers, and how it/they might
optimize code. Everyone I've ever heard of in that position has said
'for' is faster than 'foreach'.

I've tested - only C# sorry, I know this is a VB forum - several
container classes:

ArrayList
ControlCollection
StringCollection
NameObjectCollectionBase.KeysCollection

In every case 'for' is faster although it does vary quite a bit.

ControlCollection was the most extreme with 'for' being over 5 times
faster.

I would stress that even with 'foreach' it's not *slow* by any means.
And I'd also agree with everyone that was stressing that the difference
in times is so minimal that it's almost never going to be the portion of
the code the requires optimization.

Still 'for' is most definately faster than 'foreach'.

Mike




*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 21 '05 #55
Mike,
And because the actual implementation hidden there's really no way to
provide a general answer unless it's comming from someone that knows the
inside of the CLR, the the various compilers, and how it/they might
optimize code. Everyone I've ever heard of in that position has said
'for' is faster than 'foreach'.

I showed this text in this thread.

The performance difference between For and For Each loops does not appear to
be significant.

It is from Microsoft, on this page, do you think that they are included in
your sentence above.

It is in this document.
http://msdn.microsoft.com/library/de...tchPerfOpt.asp

Cor

Nov 21 '05 #56
Cor,

Interesting article. I would hope the author, who works for Microsoft,
knows what they're talking about. Although in this case I do have to
wonder given quotes like:

"...Even the slightest inefficiency inside a loop is magnified many
times over depending on the number of iterations. Specifically watch out
for repetitive property access inside your loops, using foreach instead
of for, performing expensive operations within your loops, and using
recursion."

Which is from:

http://msdn.microsoft.com/library/de.../en-us/dnpag/h
tml/scalenetchapt13.asp

Here's another one, although written earlier, that gives the logic why
it's faster:

"The JIT is smart enough (in many cases) to optimize away
bounds-checking and other things inside a For loop, but is prohibited
from doing this on foreach walks."

Which is from:

http://msdn.microsoft.com/library/de.../en-us/dndotne
t/html/dotnetperftips.asp

And here's another quote from an article that gives a 'performance
checklist'

"Use for instead of foreach in performance-critical code paths."

at:

http://msdn.microsoft.com/library/de.../en-us/dnpag/h
tml/scalenetcheck06.asp

Now even after reading that same thing in blogs and other articles I
decided to bite the bullet and actually test it myself.

Testing in .NET, even something simple like this, is difficult because
of the garbage collector and JIT compilier. But I tried to be careful:

* I used a high performance timer
* I allocated the memory for the tests at program startup
* Before each test run I did a GC.Collect, waited for finalizers and
then did another collect.
* collected multiple samples and averaged the results.

Given my test environment - .NET 1.1, Windows Server 2003 - I'm
confident that 'for' is faster than 'foreach'.

Again the caveat is that I tested with C# but if the results where
different with VB.NET then it'd be really lame for either C# or VB.NET.
(one or the other would have to have a very poor compiler).
Mike


*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Nov 21 '05 #57
Mike,

In my mind it should be as you write, because the for each has first to get
the collection and the lenght and than use that, while with a for that is
given directly.

However you told there where no official document, so that was what I
provided.

I think however as well, that the difference should be not that much and
only be important with strictly mathametical or by instance multimedia
processing. For what is C# probably more used than VBNet.

Thanks for testing this further and when I make a mistake in my assuming,
please reply?

Cor


Nov 21 '05 #58


"an*******@discussions.microsoft.com" wrote:
Is there a performance difference between this:

\\\
Dim i As Integer
For i = 0 to myObject.Controls.Count - 1
myObject.Controls(i) = ...
Next
///

and this:

\\\
Dim ctl As Control
For Each ctl In myObject.Controls
ctl = ...
Next
///

Or is For Each just "prettier"?

Thanks,

Eric

Nov 21 '05 #59
Snipped from this ng:

"I came across a reference on a web site
(http://www.personalmicrocosms.com/ht...htextbox_lines )
that said to speed up access to a rich text box's lines that you needed to
use a "foreach" loop instead of a "for" loop. This made absolutely no sense
to me, but the author had posted his code and timing results. The "foreach"
(a VB and other languages construct) was 0.01 seconds to access 1000 lines
in
rich text box, whereas the "for" loop (a traditional C++ construct) was an
astounding 25 seconds (on a not very fast PC).

I recreated a test file using the partial source code posted by the author
and verified that there is a SIGNIFICANT performance difference between the
two constructs (although on my PC is was 0.01 seconds vs 3.6 seconds - still
a noticeable delay). Unfortunately, there was no explanation as to why this
was the case and I couldn't see anything as to why one loop construct would
be different. Looking at the generated IL code with Lutz Roeder's Reflector
tool, I see that the real culprit is not the loop structure but the
get_Lines() function that is pulled out of the loop in the "foreach" loop
and
not in the "for" loop code. Which, leads to me post this question about the
differences in complier code generation/optimization and is there any
setting
that can change this.

Interestingly, this is true for both Debug and Release builds. The compiler
generated code that called that function twice for each pass of the loop
(once for the loop index check and then again for the length calculation).
Pulling out unneccessary function calls is pretty basic optimization, and I
surprised that the compiler didn't detect this.

With the IDE's intellisense and auto completion features, the "for" loop
construct shown in the code below seems like something that someone might
actually code up, and of course who would have figured out that the
get_Lines
method would be so performance intensive.

Makes me wonder if there are any other gotchas like this.

Thanks, Mike L.

----------------------------------------------------------------------------
----------------

//Simple windows form with a richtextbox control, initialized w/1000 lines
of text (e.g., "line #101", etc).

private void ForLoopButton_Click(object sender, System.EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
int Len = 0;
int Start = Environment.TickCount;
for (int i = 0; i < TheRichTextBox.Lines.Length; i++)
{
Len += TheRichTextBox.Lines[i].Length;
}
int ElapsedTime = Environment.TickCount - Start;
ResultsTextBox.Clear();
RsultsTextBox.Text = "for loop\r\n\r\nElapsed time = " + ((double)
ElapsedTime / (double) 1000.0).ToString() + " seconds\r\n\r\nResult = " +
Len.ToString();
Cursor.Current = Cursors.Arrow;
}

private void ForEachLoopButton_Click(object sender, System.EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
int Len = 0;
int Start = Environment.TickCount;
foreach (String Line in TheRichTextBox.Lines)
{
Len += Line.Length;
}
int ElapsedTime = Environment.TickCount - Start;
ResultsTextBox.Clear();
ResultsTextBox.Text = "foreach loop\r\n\r\nElapsed time = " + ((double)
ElapsedTime / (double) 1000.0).ToString() + " seconds\r\n\r\nResult = " +
Len.ToString();
Cursor.Current = Cursors.Arrow;
}

private void ForLoopButton2_Click(object sender, System.EventArgs e)
{
//Performance results now same as ForEachLoopButton_Click with the changes
made.
Cursor.Current = Cursors.WaitCursor;
int Len = 0;
int Start = Environment.TickCount;
string[] lines = TheTextBox.Lines;
for (int i = 0; i < lines.Length; i++)
{
Len += lines[i].Length;
}
int ElapsedTime = Environment.TickCount - Start;
ResultsTextBox.Clear();
RsultsTextBox.Text = "for loop\r\n\r\nElapsed time = " + ((double)
ElapsedTime / (double) 1000.0).ToString() + " seconds\r\n\r\nResult = " +
Len.ToString();
Cursor.Current = Cursors.Arrow;
}"

"Othman Kinani" <Ot**********@discussions.microsoft.com> wrote in message
news:15**********************************@microsof t.com...


"an*******@discussions.microsoft.com" wrote:
Is there a performance difference between this:

\\\
Dim i As Integer
For i = 0 to myObject.Controls.Count - 1
myObject.Controls(i) = ...
Next
///

and this:

\\\
Dim ctl As Control
For Each ctl In myObject.Controls
ctl = ...
Next
///

Or is For Each just "prettier"?

Thanks,

Eric

Nov 21 '05 #60
"Fredrik Wahlgren" <fr****************@mailbox.swipnet.se> wrote in
news:##*************@TK2MSFTNGP15.phx.gbl:
Makes me wonder if there are any other gotchas like this.


This is well known. Its because many (but not all) list type items are
maintained internally without an index (or other, such as linked items) and
the for loop requires access by index, in which such structures access by
index is slow.
--
Chad Z. Hower (a.k.a. Kudzu) - http://www.hower.org/Kudzu/
"Programming is an art form that fights back"

Empower ASP.NET with IntraWeb
http://www.atozed.com/IntraWeb/
Nov 21 '05 #61
A possible explanation would be :
- With for, it has to find out the element from its index in each loop.
- With for each it just has to locate the next element from the current one
which may be easier in some cases (such as a linked list).

It could be interesting to see if there is a difference depending on the
nature fo the enumerated collection.

Patrice
--

"Fredrik Wahlgren" <fr****************@mailbox.swipnet.se> a écrit dans le
message de news:%2*****************@TK2MSFTNGP15.phx.gbl...
Snipped from this ng:

"I came across a reference on a web site
(http://www.personalmicrocosms.com/ht...htextbox_lines ) that said to speed up access to a rich text box's lines that you needed to
use a "foreach" loop instead of a "for" loop. This made absolutely no sense to me, but the author had posted his code and timing results. The "foreach" (a VB and other languages construct) was 0.01 seconds to access 1000 lines
in
rich text box, whereas the "for" loop (a traditional C++ construct) was an
astounding 25 seconds (on a not very fast PC).

I recreated a test file using the partial source code posted by the author
and verified that there is a SIGNIFICANT performance difference between the two constructs (although on my PC is was 0.01 seconds vs 3.6 seconds - still a noticeable delay). Unfortunately, there was no explanation as to why this was the case and I couldn't see anything as to why one loop construct would be different. Looking at the generated IL code with Lutz Roeder's Reflector tool, I see that the real culprit is not the loop structure but the
get_Lines() function that is pulled out of the loop in the "foreach" loop
and
not in the "for" loop code. Which, leads to me post this question about the differences in complier code generation/optimization and is there any
setting
that can change this.

Interestingly, this is true for both Debug and Release builds. The compiler generated code that called that function twice for each pass of the loop
(once for the loop index check and then again for the length calculation).
Pulling out unneccessary function calls is pretty basic optimization, and I surprised that the compiler didn't detect this.

With the IDE's intellisense and auto completion features, the "for" loop
construct shown in the code below seems like something that someone might
actually code up, and of course who would have figured out that the
get_Lines
method would be so performance intensive.

Makes me wonder if there are any other gotchas like this.

Thanks, Mike L.

-------------------------------------------------------------------------- -- ----------------

//Simple windows form with a richtextbox control, initialized w/1000 lines
of text (e.g., "line #101", etc).

private void ForLoopButton_Click(object sender, System.EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
int Len = 0;
int Start = Environment.TickCount;
for (int i = 0; i < TheRichTextBox.Lines.Length; i++)
{
Len += TheRichTextBox.Lines[i].Length;
}
int ElapsedTime = Environment.TickCount - Start;
ResultsTextBox.Clear();
RsultsTextBox.Text = "for loop\r\n\r\nElapsed time = " + ((double)
ElapsedTime / (double) 1000.0).ToString() + " seconds\r\n\r\nResult = " +
Len.ToString();
Cursor.Current = Cursors.Arrow;
}

private void ForEachLoopButton_Click(object sender, System.EventArgs e)
{
Cursor.Current = Cursors.WaitCursor;
int Len = 0;
int Start = Environment.TickCount;
foreach (String Line in TheRichTextBox.Lines)
{
Len += Line.Length;
}
int ElapsedTime = Environment.TickCount - Start;
ResultsTextBox.Clear();
ResultsTextBox.Text = "foreach loop\r\n\r\nElapsed time = " + ((double)
ElapsedTime / (double) 1000.0).ToString() + " seconds\r\n\r\nResult = " +
Len.ToString();
Cursor.Current = Cursors.Arrow;
}

private void ForLoopButton2_Click(object sender, System.EventArgs e)
{
//Performance results now same as ForEachLoopButton_Click with the changes
made.
Cursor.Current = Cursors.WaitCursor;
int Len = 0;
int Start = Environment.TickCount;
string[] lines = TheTextBox.Lines;
for (int i = 0; i < lines.Length; i++)
{
Len += lines[i].Length;
}
int ElapsedTime = Environment.TickCount - Start;
ResultsTextBox.Clear();
RsultsTextBox.Text = "for loop\r\n\r\nElapsed time = " + ((double)
ElapsedTime / (double) 1000.0).ToString() + " seconds\r\n\r\nResult = " +
Len.ToString();
Cursor.Current = Cursors.Arrow;
}"

"Othman Kinani" <Ot**********@discussions.microsoft.com> wrote in message
news:15**********************************@microsof t.com...


"an*******@discussions.microsoft.com" wrote:
Is there a performance difference between this:

\\\
Dim i As Integer
For i = 0 to myObject.Controls.Count - 1
myObject.Controls(i) = ...
Next
///

and this:

\\\
Dim ctl As Control
For Each ctl In myObject.Controls
ctl = ...
Next
///

Or is For Each just "prettier"?

Thanks,

Eric


Nov 21 '05 #62
That's a hard question to answer:

For arrays/vectors/ILists --- collections which can be directly indexed,
it's close to a wash. (* but see below)

For other kinds of collections (hashtables, linked-lists) -- collections
which aren't or aren't easily indexed, foreach would be the faster, and
possibly the only, way to iterator through.

In some cases, bad coding just throws everything out the window, such as
the page Fredrik cites, where in the for(), he's calling "i <
TheRichTextBox.Lines.Length" each time through the loop -- except
"TheRichTextBox.Lines" builds and return s string[] each time it's called,
so 99% of the time of loop is being wasted.

And finally, the (*) note I mentioned above: The guys writing the C#
compiler knew that
for (int i = 0; i< coll.Length; ++i)
is a very common idiom in C/C++/C# code, and had the compiler recognize and
optimize it, so right now, for()s in the specific pattern are faster, but
with the next release of the C# compiler, maybe they'll get around to
optimizing foreachs.....

"Othman Kinani" <Ot**********@discussions.microsoft.com> wrote in message
news:15**********************************@microsof t.com...


"an*******@discussions.microsoft.com" wrote:
Is there a performance difference between this:

\\\
Dim i As Integer
For i = 0 to myObject.Controls.Count - 1
myObject.Controls(i) = ...
Next
///

and this:

\\\
Dim ctl As Control
For Each ctl In myObject.Controls
ctl = ...
Next
///

Or is For Each just "prettier"?

Thanks,

Eric

Nov 21 '05 #63
James Curran <ja*********@mvps.org> wrote:

<snip>
And finally, the (*) note I mentioned above: The guys writing the C#
compiler knew that
for (int i = 0; i< coll.Length; ++i)
is a very common idiom in C/C++/C# code, and had the compiler recognize and
optimize it, so right now, for()s in the specific pattern are faster, but
with the next release of the C# compiler, maybe they'll get around to
optimizing foreachs.....


Just a point of pedantry really, but I don't believe it's the C#
compiler at all - I believe it's the JIT compiler. That's good, as it
means that VB.NET and MC++ get the same advantages, so long as the JIT
recognises the code for the same kind of loop.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 21 '05 #64
Othman Kinani wrote:

"an*******@discussions.microsoft.com" wrote:

Is there a performance difference between this:

<snip for vs. foreach)

It depends on the collection you iterate over.

Possible issues that might have an impact:

- does .Length/.Count read the number from an internal variable or does
it need to do a lengthy operation to determine it (ie. split up a big
string into separate lines and count them)
- can [index] grab the correct value from an internal list or does it
need to do the same type of work as the .Length/.Count operation does ?
- how is the enumerator implemented, does it pre-cache a list (like
splitting up the text) and simply iterate through the results, or does
it have to compute the next result in some way each time ?

There's probably many more issues that will have an impact on for vs.
foreach, so the best way to determine this is to read the documentation
for the specific collection class you're using and/or profile it.

Things to consider:
- [index] calls a method, which might call a method on an internal object
- foreach constructs an object for the enumerator

Wether these things matter in your case, depends on the collection you use.

--
Lasse Vågsæther Karlsen
http://www.vkarlsen.no/
mailto:la***@vkarlsen.no
PGP KeyID: 0x0270466B
Nov 21 '05 #65
Just my 2c...

The Lines property of TextBox/RichTextBox returns a string[]. This is NOT
the native format for the TextBox, so every time you get the Lines property,
a new array is populated with the contents of the TextBox.

When you use foreach, the code becomes something like this:

string[] lines = textBox.Lines;
IEnumerator e = lines.GetEnumerator();
while (e.MoveNext())
{
string current = (string) e.Current;

...
}

See? You retrieve the Lines array only once, but when using it in a for
loop, then you build the array in every single iteration! (and maybe more
than once).

for (int i = 0; i < textBox.Lines.Length; i++) // first time - each loop
{
string current = textBox.Lines[i]; // second time - each loop
}

The compiler certainly can't take the textBox.Lines access out of the loop,
because it cannot be sure that the Lines property returns always the same
array.

If the Lines property was something like TextBoxLineCollection, then the
performance would be probably more or less the same (depending on how the
collection would be implemented).

HTH,
Stefan
"Lasse Vagsather Karlsen" <la***@vkarlsen.no> wrote in message
news:%2******************@TK2MSFTNGP15.phx.gbl...
Othman Kinani wrote:

"an*******@discussions.microsoft.com" wrote:

Is there a performance difference between this:

<snip for vs. foreach)

It depends on the collection you iterate over.

Possible issues that might have an impact:

- does .Length/.Count read the number from an internal variable or does it
need to do a lengthy operation to determine it (ie. split up a big string
into separate lines and count them)
- can [index] grab the correct value from an internal list or does it need
to do the same type of work as the .Length/.Count operation does ?
- how is the enumerator implemented, does it pre-cache a list (like
splitting up the text) and simply iterate through the results, or does it
have to compute the next result in some way each time ?

There's probably many more issues that will have an impact on for vs.
foreach, so the best way to determine this is to read the documentation
for the specific collection class you're using and/or profile it.

Things to consider:
- [index] calls a method, which might call a method on an internal object
- foreach constructs an object for the enumerator

Wether these things matter in your case, depends on the collection you
use.

--
Lasse Vagsather Karlsen
http://www.vkarlsen.no/
mailto:la***@vkarlsen.no
PGP KeyID: 0x0270466B

Nov 21 '05 #66

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

4 posts views Thread by Jean-Christophe Michel | last post: by
2 posts views Thread by matatu | last post: by
8 posts views Thread by Floris van Haaster | last post: by
13 posts views Thread by tshad | last post: by
6 posts views Thread by Michael D. Ober | last post: by
1 post views Thread by CARIGAR | last post: by
reply views Thread by suresh191 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.