# Export slowness for data ALREADY in memory

**URL:** <https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954>\
**Category:** PowerShell Help\
**Created:** [April 15, 2024, 12:15pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954 "2024-04-15T12:15:09Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Durand](https://avatars.discourse-cdn.com/v4/letter/d/bbce88/32.png) [@Durand](https://forums.powershell.org/u/Durand)\
**Post date:** [April 15, 2024, 12:15pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/1 "2024-04-15T12:15:09Z")

</div>

Hello,

I’ve been using PowerShell for several years, but I’ve noticed a very strange behavior and I’d like to get your opinion on whether this is normal or if it can be fixed/worked around.

Here’s my test: I retrieve the list of users, once by specifying a domain controller and once without.

> $UserA = Get-ADUser -Filter \* -Properties \*  
> $UserB = Get-ADUser -Filter \* -Properties \* -Server $DC

Then I export them to CSV, for example.

The problem is as follows: the export of UserB takes MUCH longer.  
I’m not referring to the time it takes to execute the Get-ADUser command, just the CSV export.  
Export A takes 0.3s  
Export B takes 46s

If I disconnect my network connection befoire the CSV export, the export of UserB is incomplete, with some properties being empty (such as the email field).  
So, it seems that PowerShell is not storing everything in memory, and some properties appear to be fetched DURING the export ☹ .

So, is this normal?  
How can I make this process faster?

Let me know if you want my test script to reproduce the behavior:

> $UserA = Get-ADUser -Filter \* -Properties \* -SearchBase $OU  
> $UserB = Get-ADUser -Filter \* -Properties \* -SearchBase $OU -Server $DC  
> (Measure-Command {$UserA | Export-Csv -Path “.\UserA.csv”}).TotalSeconds  
> “Export with DC”  
> (Measure-Command {$UserB | Export-Csv -Path “.\UserB.csv”}).TotalSeconds

---

<div class="post-metadata">

**Author:** ![krzydoug](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/krzydoug/32/1008_2.png) [@krzydoug](https://forums.powershell.org/u/krzydoug)\
**Post date:** [April 15, 2024, 1:22pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/2 "2024-04-15T13:22:44Z")

</div>

You are utilizing the pipeline for the entire command. Try storing the data before exporting

```powershell
$UserA = Get-ADUser -Filter * -Properties *
$UserA | Export-Csv -Path ".\UserA.csv"

```

and

```powershell
$UserB = Get-ADUser -Filter * -Properties * -Server $DC
$UserB | Export-Csv -Path ".\UserB.csv"

```

---

<div class="post-metadata">

**Author:** ![Durand](https://avatars.discourse-cdn.com/v4/letter/d/bbce88/32.png) [@Durand](https://forums.powershell.org/u/Durand)\
**Post date:** [April 15, 2024, 1:31pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/3 "2024-04-15T13:31:51Z")

</div>

That’s what I’m doing, the data is stored in a variable before the export.  
You have my script at the end of the message.

---

<div class="post-metadata">

**Author:** ![grey0ut](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/grey0ut/32/5310_2.png) [@grey0ut](https://forums.powershell.org/u/grey0ut)\
**Post date:** [April 15, 2024, 1:44pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/4 "2024-04-15T13:44:47Z")

</div>

that’s pretty interesting. When I’m at work I’ll try to reproduce this and see if i get the same experience.

---

<div class="post-metadata">

**Author:** ![krzydoug](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/krzydoug/32/1008_2.png) [@krzydoug](https://forums.powershell.org/u/krzydoug)\
**Post date:** [April 15, 2024, 2:06pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/5 "2024-04-15T14:06:31Z")

</div>

Oh you’re right, I didn’t see that. Since the only difference is the server being specified, can you confirm the speed is the same for all the DCs?

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [April 16, 2024, 1:15am UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/6 "2024-04-16T01:15:15Z")

</div>

Hey there Durand,

While I don’t have an answer, I wanted to simply share that I was able to replicate in my environment, at least for the ‘first’ run . If I ‘up arrow’ and rerun, its fine, and fast. Very strange. I did try a few servers and they all did the same, but not specifying the server at all, seems to ‘work around’ whatever the issue is. It’s weird because, $UserB should be the thing in ‘memory’. I confirmed in my environment that $UserA and $UserB were also identical.

Do you have to specify a DC in your process?

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [April 16, 2024, 1:24am UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/7 "2024-04-16T01:24:49Z")

</div>

Was messing around with this more… and I found a strange workaround as well, give it a shot:

```powershell
$UserB = Get-ADUser -Filter * -Properties * -SearchBase $OU -Server $DC | Select-Object -Property *
$userb | Export-Csv -Path ".\UserB.csv" -Verbose

```

By adding the Select-Object -Property \* , which would seem redundant, it’s doing something that allows that export to go faster when specifying a DC ( for the first export, which is of course probably what matters for you).

If you plan on using that as a workaround, I’d suggest adding a comment to explain why, as that would appear to be very strange to anyone reviewing your code. I’d still love to know why this is behaving like this, as it seems like a psuedo bug to me.

---

<div class="post-metadata">

**Author:** ![Durand](https://avatars.discourse-cdn.com/v4/letter/d/bbce88/32.png) [@Durand](https://forums.powershell.org/u/Durand)\
**Post date:** [April 16, 2024, 8:11am UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/8 "2024-04-16T08:11:45Z")

</div>

I specify a DC to ensure I’m on the primary and have recent information (our replication times are about 1 hour).

@dotnVo: If the export is run several times in a row, it becomes very fast indeed.  
I had noticed that too. For me, your example is functional.

I finally found the “why”:

> **[Lazy Initialization - .NET Framework](https://learn.microsoft.com/en-us/dotnet/framework/performance/lazy-initialization)**
>
> Explore lazy initialization in .NET, a performance improvement that means an object creation is deferred until the object is first used.

This also explains why your example works because the properties are initialized from the first request.

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [April 16, 2024, 2:19pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/9 "2024-04-16T14:19:46Z")

</div>

Thanks for the share! Really helpful to know that, though I wish it was more clear from a PS perspective (many folks in PS aren’t going to be aware or even know how to ‘google’ this), that by specifying a domain, it does a ‘lazy-initiationalization’ .

---

<div class="post-metadata">

**Author:** ![grey0ut](https://sea1.discourse-cdn.com/flex019/user_avatar/forums.powershell.org/grey0ut/32/5310_2.png) [@grey0ut](https://forums.powershell.org/u/grey0ut)\
**Post date:** [April 16, 2024, 2:55pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/10 "2024-04-16T14:55:31Z")

</div>

Thanks for the followup @Durand , that’s the first I had heard of lazy initialization.  
I wanted to chime in just to say I played along too (finally).  
Following your example pulling $UserA took a minute 51 seconds, and $UserB took a minute 48 seconds and they both ended up being 3806 users.  
I didn’t see anything different between the objects themselves manually indexing through a few of them, so I did the Export test and it took 1.14 seconds for $UserA and 263.9 seconds for $UserB. Immediately re-running the $UserB export only took .99 seconds.  
Definitely seems like the lazy initialization explains it.

Cool find.

BTW, not sure if it was just for your example or how you’re normally doing it but requesting all of the properties with `-Properties *` really slows things down too, depending on number of users.  
I will often write an array of the properties I really want to see and pass that as an argument.

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [April 16, 2024, 3:39pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/11 "2024-04-16T15:39:47Z")

</div>

getting all properties using Get-ADUser definitely slows things down, though in this particular case the slowness being perceived is more about the lazy init stuff. However, it would speed things up more to only get the properties you want on the get call. Typically you just won’t notice it for a few number of users as its usually very small, but for large runs, it makes a significant difference.

---

<div class="post-metadata">

**Author:** ![Durand](https://avatars.discourse-cdn.com/v4/letter/d/bbce88/32.png) [@Durand](https://forums.powershell.org/u/Durand)\
**Post date:** [April 18, 2024, 8:26am UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/12 "2024-04-18T08:26:58Z")

</div>

I’m not requesting all properties, it was just an example and to make the script as short as possible for easier readability.

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [April 18, 2024, 12:49pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/13 "2024-04-18T12:49:48Z")

</div>

Yea no worries, think it was just an observation zero made

---

<div class="post-metadata">

**Author:** ![dotnVo](https://avatars.discourse-cdn.com/v4/letter/d/4af34b/32.png) [@dotnVo](https://forums.powershell.org/u/dotnVo)\
**Post date:** [April 18, 2024, 12:49pm UTC](https://forums.powershell.org/t/export-slowness-for-data-already-in-memory/23954/14 "2024-04-18T12:49:54Z")

</div>


