Posts RSS Comments RSS 253 Posts and 411 Comments till now

Further Testing with S.DS.P (~1 sec slower)

I have to say I am in awe. I never expected to get so close to ADFind.exe in performance, but if you look below you will notice how close s.ds.p really got.

Before I show the results I want to respond to some of joe’s comments on his blog entry here: PowerShell + S.DS.Protocols Versus AdFindโ€ฆ
btw… I STRONGLY recommend reading this entry… actually subscribing to his blog. While he does spout off random quotes… he provides some incredibly useful info from time to time.

note: References to joe as joe (case intentional) is not ment as disrespect, but simply the way joe refers to himself. If you have the pleasure of getting to know him… you will understand this.

[1] I understand fully that joe really wants .NET and Powershell to succeed, but finds it unlikely.

[2] My testing (although possibly not perfect) was much more precise and I assume his testing had to be skewed by something. Its just not possible. I tried this on 4 completely different systems. Different OS’s, x64 and x86, Hyper-v and ESX, and different domain sizes. By the end of the testing.. I ran approximately 600 test (although I only documented 240.)

[3] While I can appreciate his lack of faith in measure-command. It was the only way I could remove human error and maintain an unbiased count for each test. Measure-command’s overhead is maintained completely outside of the measured expression.

[4] MOST IMPORTANTLY: Perhaps the reason joe questions my purpose of doing these tests is because I did not make it clear. My purpose in these test was to determine if it is feasible to reach the same performance of adfind.exe in Powershell. Why? adfind.exe works great, why not just that. Simply put, if I can achieve close to the same performance, I’m able to get the speed while maintaining the benefit of dealing with objects. While this concept may escape people, once you grasp it… it is key to easy and fast scripts or commands. Nothing more, nothing less. While I will not argue I like a good debate, that is not my soul reason for being.

To be clear, this is only the first step. I now need to process some properties and see if s.ds.p/powershell can compete in that area. As I was with the count I am skeptical about achieving performance even close to adfind, but perhaps that will surprise me as the search did.

[5] My count was NOT off ๐Ÿ˜› The logic of using userclass=* vs userclass=user was.

For those inclined to do so… Here is the COMPLETE output of the results without the average
Results Prod 400k VM
Small 200k Domain on Local Hardware
Small 200k Domain on VM

This first test was done in a LARGE environment with 700k+ userclass objects.

Prod 700k

This test was done on a production quality VM with approx 400k users.

Prod 400k

This test was on my Home Win2k8 DC. I only have about 200k userclass objects at home, but it is a beefy box.

Local 200k

This is on my laptop that has about 200k userclass objects as well.

VM 200k

Here are the scripts I ran for the testing

This is the actual worker code

[System.Reflection.Assembly]::LoadWithPartialName("System.DirectoryServices.Protocols") | Out-Null

$domainDN = ([ADSI]"").distinguishedName
$domain = $domainDN -replace  ",","." -replace "dc=",""

[int]$pageCount = 0
[int]$pageSize = 1000
[int]$count = 0

$connection = New-Object System.DirectoryServices.Protocols.LdapConnection($domain)  
$subtree = [System.DirectoryServices.Protocols.SearchScope]"Subtree"
$filter = "(objectclass=*)"

$searchRequest = New-Object System.DirectoryServices.Protocols.SearchRequest($DomainDN,$filter,$subtree,"1.1")  
$pagedRequest = New-Object System.DirectoryServices.Protocols.PageResultRequestControl($pageSize)
$searchRequest.Controls.add($pagedRequest) | out-null
$searchOptions = New-Object System.DirectoryServices.Protocols.SearchOptionsControl([System.DirectoryServices.Protocols.SearchOption]::DomainScope)
$searchRequest.Controls.Add($searchOptions) | out-null
while ($True)
    # Increment the pageCount by 1

    # Cast the directory response into a SearchResponse object
    $searchResponse = $connection.SendRequest($searchRequest)

    # Display the retrieved page number and the number of directory entries in the retrieved page
    # "Page:{0} Contains {1} response entries" -f $pageCount,$searchResponse.entries.count
    $count += ($searchResponse.entries).count
    # Display the entries within this page
    $searchResponse.Entries | select distinguishedName
    # if this is true, there are no more pages to request
    if ($searchResponse.Controls[0].Cookie.Length -eq 0){write-Output $count;break}

    # Set the cookie of the pageRequest equal to the cookie of the pageResponse to request the next
    # page of data in the send request and cast the directory control into a PageResultResponseControl object
    $pagedRequest.Cookie = $searchResponse.Controls[0].Cookie

Script I used to automate the 60 test per Environment.


$dn = ([ADSI]"").distinguishedName

function TestOne {
    Write-Host "  + Test ${i}.1"
    Write-Host "    + Running ADFind Test"
    $joeTime      = Measure-Command { D:\Scripts\adfind -b "$dn" -c -f "(objectclass=user)" 2>&1 | out-Null }
    Write-Host "      – $($joetime.TotalSeconds)"
    Write-Host "    + Running DSP Test"
    $DSPTime11    = Measure-command { D:\Scripts\Test-DSProtocalsSP.ps1 }
    Write-Host "      – $($DSPTime11.TotalSeconds)"
    $myresults  = "" | select @{n="ADFind"           ;e={$joeTime.TotalSeconds}},
                              @{n="DSP Using 1.1"    ;e={$DSPTime11.TotalSeconds}}
function TestTwo {
    Write-Host "  + Test ${i}.2"
    Write-Host "    + Running DSP Test"
    $DSPTime11    = Measure-command { D:\Scripts\Test-DSProtocalsSP.ps1 }
    Write-Host "      – $($DSPTime11.TotalSeconds)"
    Write-Host "    + Running ADFind Test"
    $joeTime      = Measure-Command { D:\Scripts\adfind -b "$dn" -c -f "(objectclass=user)" 2>&1 | out-Null }
    Write-Host "      – $($joetime.TotalSeconds)"
    $myresults  = "" | select @{n="ADFind"           ;e={$joeTime.TotalSeconds}},
                              @{n="DSP Using 1.1"    ;e={$DSPTime11.TotalSeconds}}

for($i = 0 ; $i -le $count ; $i++)
    Write-Host "+ Test $i"

3 Responses to “Further Testing with S.DS.P (~1 sec slower)”

  1. on 10 Jun 2008 at 6:19 am/\/\o\/\/

    Some extra test info :

    On my production AD ( not a real fast one ), the PoSH version seems even faster as the Adfind version

    AdFind V01.37.00cpp Joe Richards ( June 2007

    Using server: myTestDC:389
    Directory: Windows Server 2003

    56468 Objects returned

    First test :

    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=use… 00:01:03.0953089
    .\Test-DSProtocals.ps1 00:00:40.2770273

    PoSH version much faster, but expected could be caching .
    and yes in a series of test the results get very close,
    for this series I did start new shells started ADfind first then PoSH and other way around.

    .\Test-DSProtocals.ps1 00:00:40.5060502
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:40.1550151
    .\Test-DSProtocals.ps1 00:00:40.0990095
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:40.0890085
    .\Test-DSProtocals.ps1 00:00:40.0230019
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:39.9479944
    .\Test-DSProtocals.ps1 00:00:39.8939890
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:39.9139910
    .\Test-DSProtocals.ps1 00:00:39.9799976
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:40.1840180
    .\Test-DSProtocals.ps1 00:00:39.9769973

    (Other series)

    .\Test-DSProtocals.ps1 00:00:40.5700566
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:40.0300026
    .\Test-DSProtocals.ps1 00:00:40.0720068
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:40.0380034
    .\Test-DSProtocals.ps1 00:00:40.0870083
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:40.1310127
    .\Test-DSProtocals.ps1 00:00:39.8959892
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:40.0230019
    .\Test-DSProtocals.ps1 00:00:39.9599956
    .\adfind -b “DC=europe,DC=unity” -c -f “(objectclass=user)” 00:00:39.7709767
    .\Test-DSProtocals.ps1 00:00:39.9949991

    you can see here my results are very close with a small win for the PoSH version.

    Looks to me that in a “live” less performant AD environment (and or network connection ) the performance difference might be much smaller as in a (well connected and scaled ) VM test environment (what might explain joe’s results.

    So think a point might be, Measure and make conclusions with care ๐Ÿ˜‰

    Greetings /\/\o\/\/

  2. on 10 Jun 2008 at 2:14 pmAustin Osuide

    Hi Brandon,
    I have read joe’s post and there is not much to disagree with in his content even if his style might rub you the wrong way. I’m sure tons of folk find him a nice & interesting character and I’m sure you agree.

    The point he makes though is that your timings maybe so similar because there is some bloat within measure-object you have not accounted for (your point [3]). He attempts to measure timings out of PoSH and has dramatically and consistently different results from you. This should be cause for a reanalysis of your procedure, I would have thought, in the interest of the science ๐Ÿ™‚ .

    Mind you, IMHO this is all by the by. What PoSH gives to admins with respect to the degree of sophistication their scripts can now attain makes speed not such an issue.

  3. on 10 Jun 2008 at 2:30 pmtshell

    Austin.. I sent a more detailed response to your email, but the summary is this:

    After joe’s blog entry we did indeed test adfind outside of Powershell using ptime and the results were still consistent with my results.

    joe should be posting something about his results sometime in the future (he retested and got the same results as I did.)

Trackback this post | Feed on Comments to this post

Leave a Reply

You must be logged in to post a comment.