Windows Vista Forums
Vista Forums Home Join Vista Forums Windows 7 Forum Vista Tutorials Tags
Welcome to Windows Vista Forums. Our forum is dedicated to helping you find solutions with any problems, errors or issues you are experiencing with Windows Vista. The Vista forum also covers news and updates and has an extensive Windows Vista tutorial section that covers a wide range of tips and tricks.

Go Back   Vista Forums > Misc Newsgroups > PowerShell

Vista - Loops inside Cmdlets

Reply
 
Old 10-22-2007   #1 (permalink)
Shay Levi


 
 

Loops inside Cmdlets


When writing loops inside cmdlet in VS, what's the "best" way? (performance?)

Populate a collection and then write out the collection or write each object
when its availbale?

##### A #####

Collection<PSObject> ...

foreach(...){
Collection.Add(...)
}

WriteObject(Collection)

##### B #####

foreach(...){
WriteObject(...)
}




Shay
http://scriptolog.blogspot.com



My System SpecsSystem Spec
Old 10-22-2007   #2 (permalink)
Jon


 
 

Re: Loops inside Cmdlets

"Shay Levi" <no@xxxxxx> wrote in message
news:8766a944a76f8c9e2c5c0e8671a@xxxxxx
Quote:

>
> When writing loops inside cmdlet in VS, what's the "best" way?
> (performance?)
> Populate a collection and then write out the collection or write each
> object when its availbale?
> ##### A #####
>
> Collection<PSObject> ...
>
> foreach(...){
> Collection.Add(...)
> }
>
> WriteObject(Collection)
>
> ##### B #####
>
> foreach(...){
> WriteObject(...)
> }
>
>
>
>
> Shay
> http://scriptolog.blogspot.com
>
>

If performance is your main criteria, then I'd have thought this would be
the more efficient way of doing it, with large collections. Writing to the
pipeline in itself probably takes a bit of time / resources etc ..



foreach(...){
Collection.Add(...)
}

WriteObject(Collection)




If you have other criteria, then the other way may be better, depending on
what you're trying to achieve.



--
Jon



My System SpecsSystem Spec
Old 10-22-2007   #3 (permalink)
Joe Brinkman


 
 

Re: Loops inside Cmdlets

When you say performance I think there are a couple of types of performance
you need to take into account. When you create the collection and add your
items, then you have to have enough memory to hold all of the objects that
might be created at one time. This may not be a problem directly, but it
might be the difference between the OS needing to swap out items from the
cache in order to hold your entire collection in memory. This may be different
for each user depending on what else they have open on their machine. Having
the fastest loop, but causing hard drive thrashing would certainly not be
the best from an overall performance perspective.

The other thing to keep in mind is one of the entire pipeline. I do not
know enough about the pipeline architecture to definitively answer this,
but I would think that writing out each object individually would lead to
the best performance in the widest number of use cases since PowerShell will
start feeding the results to the next cmdlet in the pipeline as soon as it
is recieved. If you batch up the results into a single collection then you
effectively negate one of the performanc benefits of the pipeline architecture.

Joe Brinkman
----------------------------------------------------------
DotNetNuke Corp. ASP.Net MVP
www.dotnetnuke.com
----------------------------------------------------------
Quote:

> "Shay Levi" <no@xxxxxx> wrote in message
> news:8766a944a76f8c9e2c5c0e8671a@xxxxxx
>
Quote:

>> When writing loops inside cmdlet in VS, what's the "best" way?
>> (performance?)
>> Populate a collection and then write out the collection or write each
>> object when its availbale?
>> ##### A #####
>> Collection<PSObject> ...
>>
>> foreach(...){
>> Collection.Add(...)
>> }
>> WriteObject(Collection)
>>
>> ##### B #####
>>
>> foreach(...){
>> WriteObject(...)
>> }
>> Shay
>> http://scriptolog.blogspot.com
> If performance is your main criteria, then I'd have thought this would
> be the more efficient way of doing it, with large collections. Writing
> to the pipeline in itself probably takes a bit of time / resources etc
> ..
>
> foreach(...){
> Collection.Add(...)
> }
> WriteObject(Collection)
>
> If you have other criteria, then the other way may be better,
> depending on what you're trying to achieve.
>

My System SpecsSystem Spec
Old 10-22-2007   #4 (permalink)
Joe Brinkman


 
 

Re: Loops inside Cmdlets

Something I forgot to mention in my last post which should be a standard
answer about performance questions like "Which is faster X or Y": Write
the code using both methods and then run tests based on how you expect to
use the cmdlet and in a typical environment. This allows you to take the
guesswork out of the equation and forces you to really think through how
the cmdlet will be used. This also gives you a great opportunity to document
your assumptions (they may not be the same as how the cmdlet is used in the
realworld).


Joe Brinkman
----------------------------------------------------------
DotNetNuke Corp. ASP.Net MVP
www.dotnetnuke.com
----------------------------------------------------------
Quote:

> "Shay Levi" <no@xxxxxx> wrote in message
> news:8766a944a76f8c9e2c5c0e8671a@xxxxxx
>
Quote:

>> When writing loops inside cmdlet in VS, what's the "best" way?
>> (performance?)
>> Populate a collection and then write out the collection or write each
>> object when its availbale?
>> ##### A #####
>> Collection<PSObject> ...
>>
>> foreach(...){
>> Collection.Add(...)
>> }
>> WriteObject(Collection)
>>
>> ##### B #####
>>
>> foreach(...){
>> WriteObject(...)
>> }
>> Shay
>> http://scriptolog.blogspot.com
> If performance is your main criteria, then I'd have thought this would
> be the more efficient way of doing it, with large collections. Writing
> to the pipeline in itself probably takes a bit of time / resources etc
> ..
>
> foreach(...){
> Collection.Add(...)
> }
> WriteObject(Collection)
>
> If you have other criteria, then the other way may be better,
> depending on what you're trying to achieve.
>

My System SpecsSystem Spec
Old 10-22-2007   #5 (permalink)
Shay Levi


 
 

Re: Loops inside Cmdlets


Hi Joe

Mainly my thoughts were in terms of piplining. I knew the main differences
between accumulating the collection
versus pipelining each object as it's available, I just wanted to get a second/others
opinion.

Thank you Joe and Jon for sharing your thoughs, you're very helpful.


Shay
http://scriptolog.blogspot.com


Quote:

> When you say performance I think there are a couple of types of
> performance you need to take into account. When you create the
> collection and add your items, then you have to have enough memory to
> hold all of the objects that might be created at one time. This may
> not be a problem directly, but it might be the difference between the
> OS needing to swap out items from the cache in order to hold your
> entire collection in memory. This may be different for each user
> depending on what else they have open on their machine. Having the
> fastest loop, but causing hard drive thrashing would certainly not be
> the best from an overall performance perspective.
>
> The other thing to keep in mind is one of the entire pipeline. I do
> not know enough about the pipeline architecture to definitively answer
> this, but I would think that writing out each object individually
> would lead to the best performance in the widest number of use cases
> since PowerShell will start feeding the results to the next cmdlet in
> the pipeline as soon as it is recieved. If you batch up the results
> into a single collection then you effectively negate one of the
> performanc benefits of the pipeline architecture.
>
> Joe Brinkman
> ---------------------------------------------------------- DotNetNuke
> Corp. ASP.Net MVP www.dotnetnuke.com
> ----------------------------------------------------------
>
Quote:

>> "Shay Levi" <no@xxxxxx> wrote in message
>> news:8766a944a76f8c9e2c5c0e8671a@xxxxxx
Quote:

>>> When writing loops inside cmdlet in VS, what's the "best" way?
>>> (performance?)
>>> Populate a collection and then write out the collection or write
>>> each
>>> object when its availbale?
>>> ##### A #####
>>> Collection<PSObject> ...
>>> foreach(...){
>>> Collection.Add(...)
>>> }
>>> WriteObject(Collection)
>>> ##### B #####
>>>
>>> foreach(...){
>>> WriteObject(...)
>>> }
>>> Shay
>>> http://scriptolog.blogspot.com
>> If performance is your main criteria, then I'd have thought this
>> would be the more efficient way of doing it, with large collections.
>> Writing to the pipeline in itself probably takes a bit of time /
>> resources etc ..
>>
>> foreach(...){
>> Collection.Add(...)
>> }
>> WriteObject(Collection)
>> If you have other criteria, then the other way may be better,
>> depending on what you're trying to achieve.
>>

My System SpecsSystem Spec
Old 10-22-2007   #6 (permalink)
Oisin Grehan


 
 

Re: Loops inside Cmdlets

On Oct 22, 12:28 pm, Shay Levi <n...@xxxxxx> wrote:
Quote:

> Hi Joe
>
> Mainly my thoughts were in terms of piplining. I knew the main differences
> between accumulating the collection
> versus pipelining each object as it's available, I just wanted to get a second/others
> opinion.
>
> Thank you Joe and Jon for sharing your thoughs, you're very helpful.
>
> Shayhttp://scriptolog.blogspot.com
>
>
>
Quote:

> > When you say performance I think there are a couple of types of
> > performance you need to take into account. When you create the
> > collection and add your items, then you have to have enough memory to
> > hold all of the objects that might be created at one time. This may
> > not be a problem directly, but it might be the difference between the
> > OS needing to swap out items from the cache in order to hold your
> > entire collection in memory. This may be different for each user
> > depending on what else they have open on their machine. Having the
> > fastest loop, but causing hard drive thrashing would certainly not be
> > the best from an overall performance perspective.
>
Quote:

> > The other thing to keep in mind is one of the entire pipeline. I do
> > not know enough about the pipeline architecture to definitively answer
> > this, but I would think that writing out each object individually
> > would lead to the best performance in the widest number of use cases
> > since PowerShell will start feeding the results to the next cmdlet in
> > the pipeline as soon as it is recieved. If you batch up the results
> > into a single collection then you effectively negate one of the
> > performanc benefits of the pipeline architecture.
>
Quote:

> > Joe Brinkman
> > ---------------------------------------------------------- DotNetNuke
> > Corp. ASP.Net MVPwww.dotnetnuke.com
> > ----------------------------------------------------------
>
Quote:
Quote:

> >> "Shay Levi" <n...@xxxxxx> wrote in message
> >>news:8766a944a76f8c9e2c5c0e8671a@xxxxxx
> >>> When writing loops inside cmdlet in VS, what's the "best" way?
> >>> (performance?)
> >>> Populate a collection and then write out the collection or write
> >>> each
> >>> object when its availbale?
> >>> ##### A #####
> >>> Collection<PSObject> ...
> >>> foreach(...){
> >>> Collection.Add(...)
> >>> }
> >>> WriteObject(Collection)
> >>> ##### B #####
>
Quote:
Quote:

> >>> foreach(...){
> >>> WriteObject(...)
> >>> }
> >>> Shay
> >>>http://scriptolog.blogspot.com
> >> If performance is your main criteria, then I'd have thought this
> >> would be the more efficient way of doing it, with large collections.
> >> Writing to the pipeline in itself probably takes a bit of time /
> >> resources etc ..
>
Quote:
Quote:

> >> foreach(...){
> >> Collection.Add(...)
> >> }
> >> WriteObject(Collection)
> >> If you have other criteria, then the other way may be better,
> >> depending on what you're trying to achieve.- Hide quoted text -
>
> - Show quoted text -
In my experience, writing one at a time is nearly always -- if not
always -- the right answer. I won't repeat what Joe said, but you can
take it that I agree with him 100%. Writing one at a time provides the
widest range of options for the cmdlet's consumer; if a collection is
needed, just assign to a variable. Yes, it's slower, but defnitely the
most flexible.

- Oisin

- Oisin

My System SpecsSystem Spec
Old 10-22-2007   #7 (permalink)
Shay Levi


 
 

Re: Loops inside Cmdlets

10x Oisin

Shay
http://scriptolog.blogspot.com


Quote:

> On Oct 22, 12:28 pm, Shay Levi <n...@xxxxxx> wrote:
>
Quote:

>> Hi Joe
>>
>> Mainly my thoughts were in terms of piplining. I knew the main
>> differences
>> between accumulating the collection
>> versus pipelining each object as it's available, I just wanted to get
>> a second/others
>> opinion.
>> Thank you Joe and Jon for sharing your thoughs, you're very helpful.
>>
>> Shayhttp://scriptolog.blogspot.com
>>
Quote:

>>> When you say performance I think there are a couple of types of
>>> performance you need to take into account. When you create the
>>> collection and add your items, then you have to have enough memory
>>> to hold all of the objects that might be created at one time. This
>>> may not be a problem directly, but it might be the difference
>>> between the OS needing to swap out items from the cache in order to
>>> hold your entire collection in memory. This may be different for
>>> each user depending on what else they have open on their machine.
>>> Having the fastest loop, but causing hard drive thrashing would
>>> certainly not be the best from an overall performance perspective.
>>>
>>> The other thing to keep in mind is one of the entire pipeline. I do
>>> not know enough about the pipeline architecture to definitively
>>> answer this, but I would think that writing out each object
>>> individually would lead to the best performance in the widest number
>>> of use cases since PowerShell will start feeding the results to the
>>> next cmdlet in the pipeline as soon as it is recieved. If you batch
>>> up the results into a single collection then you effectively negate
>>> one of the performanc benefits of the pipeline architecture.
>>>
>>> Joe Brinkman
>>> ----------------------------------------------------------
>>> DotNetNuke Corp. ASP.Net
>>> MVPwww.dotnetnuke.com
>>> ----------------------------------------------------------
>>>
>>>> "Shay Levi" <n...@xxxxxx> wrote in message
>>>> news:8766a944a76f8c9e2c5c0e8671a@xxxxxx
>>>>> When writing loops inside cmdlet in VS, what's the "best" way?
>>>>> (performance?)
>>>>> Populate a collection and then write out the collection or write
>>>>> each
>>>>> object when its availbale?
>>>>> ##### A #####
>>>>> Collection<PSObject> ...
>>>>> foreach(...){
>>>>> Collection.Add(...)
>>>>> }
>>>>> WriteObject(Collection)
>>>>> ##### B #####
>>>>> foreach(...){
>>>>> WriteObject(...)
>>>>> }
>>>>> Shay
>>>>> http://scriptolog.blogspot.com
>>>> If performance is your main criteria, then I'd have thought this
>>>> would be the more efficient way of doing it, with large
>>>> collections. Writing to the pipeline in itself probably takes a bit
>>>> of time / resources etc ..
>>>>
>>>> foreach(...){
>>>> Collection.Add(...)
>>>> }
>>>> WriteObject(Collection)
>>>> If you have other criteria, then the other way may be better,
>>>> depending on what you're trying to achieve.- Hide quoted text -
>> - Show quoted text -
>>
> In my experience, writing one at a time is nearly always -- if not
> always -- the right answer. I won't repeat what Joe said, but you can
> take it that I agree with him 100%. Writing one at a time provides the
> widest range of options for the cmdlet's consumer; if a collection is
> needed, just assign to a variable. Yes, it's slower, but defnitely the
> most flexible.
>
> - Oisin
>
> - Oisin
>

My System SpecsSystem Spec
Old 10-22-2007   #8 (permalink)
John Vottero


 
 

Re: Loops inside Cmdlets

"Jon" <Email_Address@xxxxxx> wrote in message
news:eeW6%23TLFIHA.3360@xxxxxx
Quote:

> "Shay Levi" <no@xxxxxx> wrote in message
> news:8766a944a76f8c9e2c5c0e8671a@xxxxxx
Quote:

>>
>> When writing loops inside cmdlet in VS, what's the "best" way?
>> (performance?)
>> Populate a collection and then write out the collection or write each
>> object when its availbale?
>> ##### A #####
>>
>> Collection<PSObject> ...
>>
>> foreach(...){
>> Collection.Add(...)
>> }
>>
>> WriteObject(Collection)
>>
>> ##### B #####
>>
>> foreach(...){
>> WriteObject(...)
>> }
>>
>>
>>
>>
>> Shay
>> http://scriptolog.blogspot.com
>>
>>
>
>
> If performance is your main criteria, then I'd have thought this would be
> the more efficient way of doing it, with large collections. Writing to the
> pipeline in itself probably takes a bit of time / resources etc ..
>
>
>
> foreach(...){
> Collection.Add(...)
> }
>
> WriteObject(Collection)
>
As others have said, writing collections to the pipeline it not usually the
best thing to do and, there is NO performance gain. The only thing
WriteObject(obj) does is Collection.Add(obj).

My System SpecsSystem Spec
Old 10-22-2007   #9 (permalink)
Keith Hill [MVP]


 
 

Re: Loops inside Cmdlets

"Shay Levi" <no@xxxxxx> wrote in message
news:8766a944a76f8c9e2c5c0e8671a@xxxxxx
Quote:

>
> When writing loops inside cmdlet in VS, what's the "best" way?
> (performance?)
> Populate a collection and then write out the collection or write each
> object when its availbale?
> ##### A #####
>
> Collection<PSObject> ...
>
> foreach(...){
> Collection.Add(...)
> }
>
> WriteObject(Collection)
I agree with the advice about streaming objects down the pipeline. However
there are times when outputting a collection is the way to go. For instance,
if you were to implement your own sort cmdlet, you would like need to
accumulate all objects first into a collection most likely, sort them and
then write the sorted collection to the pipe.

--
Keith

My System SpecsSystem Spec
Old 10-23-2007   #10 (permalink)
Jon


 
 

Re: Loops inside Cmdlets


"John Vottero" <JVottero@xxxxxx> wrote in message
news:612536D6-C670-44DC-8B71-5BAD1DE4962C@xxxxxx
Quote:

> As others have said, writing collections to the pipeline it not usually
> the best thing to do and, there is NO performance gain. The only thing
> WriteObject(obj) does is Collection.Add(obj).
>


Actually that's incorrect. There is a performance gain with writing just the
collection to the pipeline, and for large collections the difference can be
quite significant. This is presumably because you're writing just the one
object (or perhaps just a reference to it) to the pipeline.

Compile the following code (VB) in a cmdlet and you'll see what I mean
(results below the code).

'Code within test-speed cmdlet...

'----------------------------------------
Dim Col As New Collection
Dim a As Integer

Select Case Options
Case 1
'OPTION 1
For a = 1 To Count
Col.Add(a)
Next
WriteObject(Col, True)

Case 2
'OPTION 2
For a = 1 To Count
Col.Add(a)
Next
WriteObject(Col)

Case 3

'OPTION 3
For a = 1 To Count
WriteObject(a)
Next


End Select


'------------------------------------------------------

RESULTS....

PS (1) > (measure-command {test-speed -Count 100000 -Options
1 }).TotalSeconds
2.544173
PS (2) > (measure-command {test-speed -Count 100000 -Options
2 }).TotalSeconds
0.1288471
PS (3) > (measure-command {test-speed -Count 100000 -Options
3 }).TotalSeconds
2.7609268
PS (4) >


So the quickest option is clearly 'case 2' - by a long way.


Whether or not it's better or worse is a bit like debating whether it's
better to use a small spoon or a big spoon. Depends what you're trying to
do.


--
Jon


My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
Vista loops on start up after avg is running Vista General
change permission on all files inside a folder or hundreds of file inside a folder Vista security
Traps and Foreach loops PowerShell
possible bug with using the $foreach keyword inside foreach loops.. PowerShell
Next fucntion in loops? PowerShell


Vista Forums is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media Ltd

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46