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 - How can I avoid an out of memory exception?

Reply
 
Old 11-13-2006   #1 (permalink)
JW


 
 

How can I avoid an out of memory exception?

I have some Internet log files that run 8-9GB each. I am trying to convert
the format to one that my reporting software will accept. This code works on
smaller files but when I run it against the big ones I get an out of memory
exception.

filter convert
{
if ($_.linenumber -gt 4)
{
$line = $_.line -replace " \(.*\)","-"
$line = $line.split()
$time = ($line[0] +" "+ $line[1])
$t = [datetime] $time
$newtime = "`"[" + $t.tolocaltime().toString("dd/MMM/yyyy:HH:MM:ss") + "
-0" + $hour + "00]`""
$newtime +" `""+ $line[23] +"`" "+ $line[3] +" "+ $line[9]+ "://" +
$line[10] + $line[12] +" "+ $line[20] +" "+ $line[21] +" "+ $line[27] +" "+
$line[6]
}
If ($_.linenumber -eq 4) {"#Fields: localtime s-computername c-ip c-uri
sc-filter-result cs-categories cs-user sc-bytes"}
If ($_.linenumber -le 3) {$_.line}
}

$files = dir
measure-command {foreach ($file in $files) {get-content $file -readCount 1
-include *.txt | convert | set-content "$file.log"}}

This throws and out of memory exception. I have also tried the following...

$files = dir
measure-command {foreach ($file in $files) {select-string $file.fullname
-pattern "." | convert | set-content "$file.log"}}

With the same result. I think what is happening is that select-string and
get-content are building a collection which contains each line in the file
which is using all of my system memory.

How can I read in one line at a time from a file and pass it along the
pipeline without creating a collection?

Thanks,
Jonathan

My System SpecsSystem Spec
Old 11-13-2006   #2 (permalink)
Adam Milazzo


 
 

Re: How can I avoid an out of memory exception?

JW wrote:
> With the same result. I think what is happening is that select-string and
> get-content are building a collection which contains each line in the file
> which is using all of my system memory.

That would be pretty lame, but you may be right. :-/

> How can I read in one line at a time from a file and pass it along the
> pipeline without creating a collection?

I think your best bet is to use .NET. Unfortunately, I don't think
there's a built-in line enumerator.

But I think you could create one and compile it into your utilities DLL
(say "JW.Utilities.dll") which you load in your profile:

[Reflection.Assembly]::LoadWithPartialName("JW.Utilities")

Assuming it's in the GAC... or:

[Reflection.Assembly]::LoadFrom("c:/myutils/JW.Utilities.dll")

If it's not.

Then you can use it like so:

PS> new-object JW.LineReader c:/foo.log | convert | set-content bar.log


Here's a bit of (untested) code to implement a simple line enumerator.
I'm assuming that PowerShell can use any IEnumerator object. If not, you
may need to implement IEnumerable<string> as well.


public class LineEnumerator : IEnumerator<string>
{
public LineEnumerator(string path)
: this(new StreamReader(path)) { }

public LineEnumerator(Stream stream)
: this(new StreamReader(stream)) { }

public LineEnumerator(TextReader reader)
{
if(reader == null) throw new ArgumentNullException();
this.reader = reader;
}

readonly TextReader reader;

#region IEnumerator Members
public string Current
{
get
{
if(currentLine == null) throw new InvalidOperationException();
return currentLine;
}
}

public void Dispose()
{
reader.Dispose();
}

object System.Collections.IEnumerator.Current
{
get { return Current; }
}

public bool MoveNext()
{
currentLine = reader.ReadLine();
return currentLine != null;
}

public void Reset()
{
throw new NotSupportedException();
}
#endregion

string currentLine;
}
My System SpecsSystem Spec
Old 11-14-2006   #3 (permalink)
dreeschkind


 
 

Re: How can I avoid an out of memory exception?

"Adam Milazzo" wrote:

> [Reflection.Assembly]::LoadFrom("c:/myutils/JW.Utilities.dll")

<snip>
> PS> new-object JW.LineReader c:/foo.log | convert | set-content bar.log

<snip>

Using .NET directly from PowerShell I think you should avoid forward slashes
and use backslashes instead.

--
greetings
dreeschkind
My System SpecsSystem Spec
Old 11-14-2006   #4 (permalink)
gaurhoth


 
 

Re: How can I avoid an out of memory exception?

JW,

Might want to try using .NET framework as think Get-Content reads the entire
file into memory... obviously with an 8gb file that presents a problem.
Here's a very simple example...

$filepath = "c:\whatever.txt"
$read = [system.io.file]::OpenText($filepath)
while ($read.Peek() -ne -1) {
write-host $read.readline()
}

If you do a $read | gm, you'll notice that [system.io.file]::OpenText
returns a System.IO.StreamReader type. If you look at the properties and
methods of this type, you'll notice other options for reading the file.

Should get you started.

Gaurhoth


"JW" <JW@discussions.microsoft.com> wrote in message
news:85655ABC-8765-4214-B7E2-51F3067A38CF@microsoft.com...
>I have some Internet log files that run 8-9GB each. I am trying to convert
> the format to one that my reporting software will accept. This code works
> on
> smaller files but when I run it against the big ones I get an out of
> memory
> exception.
>
> filter convert
> {
> if ($_.linenumber -gt 4)
> {
> $line = $_.line -replace " \(.*\)","-"
> $line = $line.split()
> $time = ($line[0] +" "+ $line[1])
> $t = [datetime] $time
> $newtime = "`"[" + $t.tolocaltime().toString("dd/MMM/yyyy:HH:MM:ss") + "
> -0" + $hour + "00]`""
> $newtime +" `""+ $line[23] +"`" "+ $line[3] +" "+ $line[9]+ "://" +
> $line[10] + $line[12] +" "+ $line[20] +" "+ $line[21] +" "+ $line[27] +"
> "+
> $line[6]
> }
> If ($_.linenumber -eq 4) {"#Fields: localtime s-computername c-ip c-uri
> sc-filter-result cs-categories cs-user sc-bytes"}
> If ($_.linenumber -le 3) {$_.line}
> }
>
> $files = dir
> measure-command {foreach ($file in $files) {get-content $file -readCount 1
> -include *.txt | convert | set-content "$file.log"}}
>
> This throws and out of memory exception. I have also tried the
> following...
>
> $files = dir
> measure-command {foreach ($file in $files) {select-string $file.fullname
> -pattern "." | convert | set-content "$file.log"}}
>
> With the same result. I think what is happening is that select-string and
> get-content are building a collection which contains each line in the file
> which is using all of my system memory.
>
> How can I read in one line at a time from a file and pass it along the
> pipeline without creating a collection?
>
> Thanks,
> Jonathan



My System SpecsSystem Spec
Old 11-14-2006   #5 (permalink)
Flowering Weeds


 
 

Re: How can I avoid an out of memory exception?



> I have some Internet log files
> that run 8-9GB each. I am trying to
> convert the format to one that my
> reporting software will accept.


Perhaps Microsoft's Log Parser
http://www.microsoft.com/technet/scr...r/default.mspx



My System SpecsSystem Spec
Old 11-14-2006   #6 (permalink)
klumsy@xtra.co.nz


 
 

Re: How can I avoid an out of memory exception?

this test:

filter testfilter {
write-Host "test $_"
$_
}

1..10 | % {"hello $_" } > c:\outtest.txt
gc c:\outtest.txt | % {write-Host "before: $_";$_ } | testfilter | %
{write-Host "after: $_";$_}
DIR C:\OUTTEST.TXT | select-String "hello" | % {$_.line} | %
{write-Host "before: $_";$_ } | testfilter | % {write-Host "after:
$_";$_}
gc c:\outtest.txt | % {write-Host "before: $_";$_ } | % {write-Host
"after: $_";$_}

shows that neither select-string nor getcontent are blocking the
pipeline... i'll have to look at your filter to see more.. maybe
another way to test is to rewrite your filter as a function with -begin
-process and -end sections..

My System SpecsSystem Spec
Old 11-14-2006   #7 (permalink)
Bruce Payette [MSFT]


 
 

Re: How can I avoid an out of memory exception?

Actually the problem appears to be in set-content. We're investigating. For
now, it you use out-file instead of set-content, you shouldn't get the
exception.

-bruce

--
Bruce Payette [MSFT]
Windows PowerShell Technical Lead
Microsoft Corporation
This posting is provided "AS IS" with no warranties, and confers no rights.



<klumsy@xtra.co.nz> wrote in message
news:1163534623.889212.180670@h48g2000cwc.googlegroups.com...
> this test:
>
> filter testfilter {
> write-Host "test $_"
> $_
> }
>
> 1..10 | % {"hello $_" } > c:\outtest.txt
> gc c:\outtest.txt | % {write-Host "before: $_";$_ } | testfilter | %
> {write-Host "after: $_";$_}
> DIR C:\OUTTEST.TXT | select-String "hello" | % {$_.line} | %
> {write-Host "before: $_";$_ } | testfilter | % {write-Host "after:
> $_";$_}
> gc c:\outtest.txt | % {write-Host "before: $_";$_ } | % {write-Host
> "after: $_";$_}
>
> shows that neither select-string nor getcontent are blocking the
> pipeline... i'll have to look at your filter to see more.. maybe
> another way to test is to rewrite your filter as a function with -begin
> -process and -end sections..
>



My System SpecsSystem Spec
Reply

Thread Tools


Similar Threads
Thread Forum
What is the consensus? Avoid SP1? Vista General
Exception stack is corrupt when catching and storing the exception .NET General
Vista Install Error: Exception Unknown Software Exception Vista installation & setup
how to avoid downclocking while using 3 or 4 memory slots Vista hardware & devices
How to avoid overwriting XP Vista General


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