Page 1 of 1 1
Topic Options
#131956 - 2005-01-05 10:37 AM Kix script give high cpu usage
jan Offline
Getting the hang of it

Registered: 2004-07-07
Posts: 66
Hi,

I've made a KIX script that reads a txt-file and the txt-file is only 800KB. When I run the script on my server it has 100% CPU usage. Is there any way I can run the script with low CPU usages/set priority

Jan

PS The script look like this:

FUNCTION READFILE($_file,optional $_delim,optional $_amount)
DIM $

$=$_file
$_delim=""+$_delim
$_amount=0+$_amount
$_file=FREEFILEHANDLE()
IF 0=$_file EXIT 1 ENDIF
IF OPEN($_file,$) EXIT 2 ENDIF
$=""
DO $=$+READLINE($_file)+CHR(10) UNTIL @error
$ReadFile=SPLIT(LEFT($,LEN($)-2),CHR(10))
$=CLOSE($_file)
$=""

IF $_amount<0
FOR $_file=$_amount+UBOUND($ReadFile)+1 TO UBOUND($ReadFile)
$=$+$ReadFile[$_file]+CHR(10)
NEXT
$ReadFile=SPLIT(LEFT($,LEN($)-1),CHR(10))
ENDIF

IF $_amount>0
FOR $_file=0 TO $_amount-1
$=$+$ReadFile[$_file]+CHR(10)
NEXT
$ReadFile=SPLIT(LEFT($,LEN($)-1),CHR(10))
ENDIF

IF $_delim $ReadFile=JOIN($ReadFile,$_delim) ENDIF
EXIT 0

ENDFUNCTION

FUNCTION GET_AVG

DIM $x $z $y $line $lines $min

$min=403
$x = "Pooled Available:"

FOR EACH $line IN ReadFile($log,,)
$array = $line+@CRLF
IF INSTR($array,$x) <> 0
$y = RIGHT($array,5)
$y = VAL($y)
$sum = $sum + $y
$lines = $lines + 1
IF $max < $y $max = $y ENDIF
IF $min => $y $min = $y ENDIF

ENDIF
NEXT
$avg = $sum / $lines

ENDFUNCTION

FUNCTION ADD2LOG

SHELL '%comspec% /c clicense connections > $file'

FOR EACH $line IN ReadFile($file,,22)
$array=$array+$line+@CRLF
NEXT
$InUse= SUBSTR($array,332,500)
IF @error "error @error" ENDIF

ENDFUNCTION

;====== Main program

$file="\\dkbirfs01\q8logon$\Scripts\screendump.log"
$log="\\dkbirfs01\q8logon$\Scripts\ctxcount.log"
;$log="h:\Scripts\ctxcount.log" ; just for testing

GET_AVG
ADD2LOG

REDIRECTOUTPUT($log,0)
"@CRLF***********************************@CRLF"
"Started Date: @DATE Time: @TIME@CRLF"

"$InUse"
"@CRLFAVG licenses available: $avg@CRLF"
"MIN licenses available: $min@CRLF"
"MAX licenses available: $max@CRLF"

Top
#131957 - 2005-01-05 10:44 AM Re: Kix script give high cpu usage
Radimus Moderator Offline
Moderator
*****

Registered: 2000-01-06
Posts: 5187
Loc: Tampa, FL
the reason you probably have 100 cpu is you have a runaway code...

there is probably a faw in some loop that is trapping the code and is making it stuck in some endless loop

If it wasn't 4:30 in the morning, I'd look closer at it, but I'm having a hard time focusing on the screen
_________________________
How to ask questions the smart way <-----------> Before you ask

Top
#131958 - 2005-01-05 11:21 AM Re: Kix script give high cpu usage
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Yes, there are two things you can do.

1) Give up some time using SLEEP.
2) Start in a low priority using the DOS "START" built-in.

The second method is definately the better one.

As a general aside, normally you *want* your CPU to be at 100% while the script is running. If your CPU is running at less than 100% then it is underutilised and you've spent money on it that you didn't need to.

The only time you want to start to give up CPU time is when another process (usually an interactive one) needs it. Windows has at long last got a half-decent scheduler, so you should be able to leave it up to the system to organise CPU usage.

An 800KB file is pretty large - the ReadFile() UDF is probably highly inefficient with this size of file.

Unless you need to make multiple passes through the file I strongly recommend that you use basic KiXtart IO (OPEN/READ/CLOSE) to access the data rather than the udf. This will speed your script up quite a bit.

Top
#131959 - 2005-01-05 11:52 AM Re: Kix script give high cpu usage
jan Offline
Getting the hang of it

Registered: 2004-07-07
Posts: 66
Hi,

The scripts runs for about 15 min and finished perfectly, so I don't think it's a running loop

Jan

Top
#131960 - 2005-01-05 11:57 AM Re: Kix script give high cpu usage
jan Offline
Getting the hang of it

Registered: 2004-07-07
Posts: 66
Hi,

Thanks for your reply. I'll try to use the OPEN/READ instead.

Jan

Top
#131961 - 2005-01-05 03:01 PM Re: Kix script give high cpu usage
Bryce Offline
KiX Supporter
*****

Registered: 2000-02-29
Posts: 3167
Loc: Houston TX
Actualy his readfile() UDF is using the OPEN() and Readline() commands... so i doubt that the CPU usage will drop when dealing with such a LARGE file.

You might want to give the WSH file read utils a try.... something like this...

Code:

;this Function will load the contents of a text file into an array
Function loadfile($file)
DIM $fso,$f,$fs
$fso = CreateObject("Scripting.FileSystemObject")
$f = $fso.GetFile($file)
If @ERROR Exit(2) EndIf
$fs = $f.OpenAsTextStream(1)
$loadfile = Split($fs.Read($f.size),@CRLF)
Exit(@ERROR)
EndFunction



Bryce

Top
#131962 - 2005-01-05 03:21 PM Re: Kix script give high cpu usage
jan Offline
Getting the hang of it

Registered: 2004-07-07
Posts: 66
Hi,

just tried your code and it works like a charm. From running in 10-15 min it now only run for 30 sec.

You are me hero

Jan

Top
#131963 - 2005-01-05 03:45 PM Re: Kix script give high cpu usage
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Quote:

Actualy his readfile() UDF is using the OPEN() and Readline() commands... so i doubt that the CPU usage will drop when dealing with such a LARGE file.




No, that's not correct. Look at the udf more closely, and you will see the obvious problems.

To elaborate, there are two major inefficiencies in the ReadFile() udf.

The most obvious is where you specify a postive limit on the number of lines to be returned. In this case the entire file is read before the code checks to see if there is a limit. This means that if you need the first 10 lines from your 10,000 line file all 10,000 lines will be read anyway.

The second less obvious problem is how ReadFile() manipulates the data.

As each line is read from the file buffer, it is catenated to the end of a string. This string gets longer and longer until it eventually becomes the size of your file. As you can imagine, string manipulations on data this size become slower as the string gets larger, and with a 800KB text file there is likely to be a large number of iterations of the ReadLine() loop.

The string is then converted to an array - again this is not a trivial task for a string of this length.

All this string manipulation occurs in core memory and requires repeated creation and destruction of temporary variable / stack space in the scripts private process space.

The string maniplation is where the majority CPU cycles are burned, not on the file IO.

The reason for moving the ReadLine() activity to the main script is that the temporary string is not created so we lose the massive overhead. As we need to iterate the result anyway we also save the overhead of the do..until loop in the UDF.

However, FSO is a good option too. In this case even with the Split() it may well be quicker than using KiXtart file IO

[edit]
Contribution to the Secret Long Line Policemans ball to follow...
[/edit]


Edited by Richard H. (2005-01-06 09:15 AM)

Top
#131964 - 2005-01-05 03:53 PM Re: Kix script give high cpu usage
Les Offline
KiX Master
*****

Registered: 2001-06-11
Posts: 12734
Loc: fortfrances.on.ca
Nice code Bryce, except for the use of parens to force precedence on the Exit parm where none is needed.
_________________________
Give a man a fish and he will be back for more. Slap him with a fish and he will go away forever.

Top
#131965 - 2005-01-05 05:00 PM Re: Kix script give high cpu usage
Bryce Offline
KiX Supporter
*****

Registered: 2000-02-29
Posts: 3167
Loc: Houston TX
Richard,

I will admit i didn't fully process his code before making my post. I looked at it enough to see the readline() loop and knew from personal experience that my bit of FSO code would handle a large file a lot better than any readline() solution.

When i first saw the use of a readfile() UDF in Jan's code I was assuming it was this UDF. ReadFile() (by Radimus), but i see now that we have 2 ReadFile() (by Jooel) UDF's in the UDF forum.

Looks like Jan is using Jooel's version.


Top
#131966 - 2005-01-05 05:01 PM Re: Kix script give high cpu usage
Bryce Offline
KiX Supporter
*****

Registered: 2000-02-29
Posts: 3167
Loc: Houston TX
Quote:

Nice code Bryce, except for the use of parens to force precedence on the Exit parm where none is needed.




I wrote that back before the EXIT police started their crack down.....

Top
#131967 - 2005-01-05 05:03 PM Re: Kix script give high cpu usage
Bryce Offline
KiX Supporter
*****

Registered: 2000-02-29
Posts: 3167
Loc: Houston TX
actualy need to fine richard for using the "code" tags in place of the "quote" tages and causing a long line
Top
#131968 - 2005-01-06 02:18 AM Re: Kix script give high cpu usage
kholm Offline
Korg Regular
*****

Registered: 2000-06-19
Posts: 714
Loc: Randers, Denmark
Just to check the performance of ReDim i made the following function.
It uses only KiX (No COM-objects)
It seems to be faster than Bryce's LoadFile()

Code:

Function ReadFile($file)
Dim $i,$f,$L
$f = FreeFileHandle
$i = Open($f,$file)
If @Error
Exit @Error
EndIf
$i = 0
$L = ReadLine($f)
While @Error = 0
ReDim Preserve $ReadFile[$i]
$ReadFile[$i] = $L
$i = $i + 1
$L = ReadLine($f)
Loop
$i = Close($f)
Exit VarType($ReadFile) = 0 ; Exitcode 1 if file is empty
EndFunction



Small code is not allways the fastest

In many other situations we might consider using the force of KiX.
This could be a starter for a new thread on performans of KiX for long strings, Split, Join and Redim Of arrays and ...

-Erik

Top
#131969 - 2005-01-06 03:08 AM Re: Kix script give high cpu usage
Bryce Offline
KiX Supporter
*****

Registered: 2000-02-29
Posts: 3167
Loc: Houston TX
faster.... I dont know.......

Code:

$start = cdbl(""+flipctime(@date,@time)+"."+@msecs)
$file = loadfile("dir.txt")
$end = cdbl(""+flipctime(@date,@time)+"."+@msecs)
? "Loadfile() = " $end - $start

$start = cdbl(""+flipctime(@date,@time)+"."+@msecs)
$file = readfile("dir.txt")
$end = cdbl(""+flipctime(@date,@time)+"."+@msecs)
? "ReadFile() = " $end - $start



Function ReadFile($file)
Dim $i,$f,$L
$f = FreeFileHandle
$i = Open($f,$file)
If @Error
Exit @Error
EndIf
$i = 0
$L = ReadLine($f)
While @Error = 0
ReDim Preserve $ReadFile[$i]
$ReadFile[$i] = $L
$i = $i + 1
$L = ReadLine($f)
Loop
$i = Close($f)
Exit VarType($ReadFile) = 0 ; Exitcode 1 if file is empty
EndFunction

;this Function will load the contents of a text file into an array
Function loadfile($file)
DIM $fso,$f,$fs
$fso = CreateObject("Scripting.FileSystemObject")
$f = $fso.GetFile($file)
If @ERROR Exit(2) EndIf
$fs = $f.OpenAsTextStream(1)
$loadfile = Split($fs.Read($f.size),@CRLF)
Exit(@ERROR)
EndFunction

Function FlipcTime($date,$time,optional $tz)
dim $y,$m,$d
$date = split($date,"/")
if ubound($date) <> 2 exit(1) endif
$y=val($date[0]) $m=val($date[1]) $d=val($date[2])
if $m<3
$m=$m+12
$y=$y-1
endif
$Date=$d+(153*$m-457)/5+365*$y+$y/4-$y/100+$y/400-306
$time = split($time,":")
select
case ubound($time)=1
redim preserve $time[2]
$time[2]=0
case ubound($time)=2
case 1
exit(1)
endselect
$time = (val($time[0])*3600)+(val($time[1])*60)+val($time[2])
$flipctime = IIF($tz,(($date-719163)*86400 + $time)-($tz*3600),($date-719163)*86400 + $time)
endfunction





dir.txt is a "dir c:\ /s > dir.txt" and is a file that is 3.9m in size.

this is the results for time in seconds... I ran the above script 5 times in a row
Code:

C:\temp>kix32 readfile.kix

Loadfile() = 0.75
ReadFile() = 1.42199993133545
C:\temp>kix32 readfile.kix

Loadfile() = 0.75
ReadFile() = 1.42200016975403
C:\temp>kix32 readfile.kix

Loadfile() = 0.75
ReadFile() = 2.12400007247925
C:\temp>kix32 readfile.kix

Loadfile() = 0.765000104904175
ReadFile() = 1.42199993133545
C:\temp>kix32 readfile.kix

Loadfile() = 0.766000032424927
ReadFile() = 1.42199993133545
C:\temp>



Bryce

Top
#131970 - 2005-01-06 04:02 AM Re: Kix script give high cpu usage
Chris S. Offline
MM club member
*****

Registered: 2002-03-18
Posts: 2368
Loc: Earth
Well, don't forget that we're talking about a large file here (the orginal post, remember it?). If you read the manual about Open(), it says that Open() reads the entire file into memory and that it is not optimized for larger operations.
Top
#131971 - 2005-01-06 03:34 PM Re: Kix script give high cpu usage
ChristopheM Offline
Hey THIS is FUN
*****

Registered: 2002-05-13
Posts: 309
Loc: STRASBOURG, France
I did some modifications to Bryce's source code and the results are a bit differents :
Code:
break on

dim $start, $arrInc, $inc, $file

$arrInc = 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192

for each $inc in $arrInc
dim $file

$start=@TICKS
$file = ""
$file = loadfile("dir.txt")
$file = ""
? "Loadfile() = " @TICKS - $start

chr(9)

$start=@TICKS
$file = ""
$file = readfile("dir.txt", $inc, 0)
$file = ""

"constant increment ReadFile("+$inc+") = " @TICKS - $start

chr(9)

$start=@TICKS
$file = ""
$file = readfile("dir.txt", $inc, 1)
$file = ""

"variable increment ReadFile("+$inc+") = " @TICKS - $start
next
?
exit

; will load the contents of a text file into an array only with Kix
Function ReadFile($file, optional $inc, optional $incvariable )
Dim $, $i,$f,$L, $j

if not $inc $inc = 1 endif

Dim $ReadFile[$inc]

$f = FreeFileHandle()
$ = Open($f,$file)
if @Error
Exit @Error
endIf

$i = -1
$j = 0
$L = ReadLine($f)
While not @Error
$i = $i + 1
if $i > $j
$j = $j + $inc
ReDim Preserve $ReadFile[$j]
if $incvariable
$inc = $inc + $inc
endif
endif
$ReadFile[$i] = $L
$L = ReadLine($f)
Loop
$ = Close($f)
if $i=-1
$ReadFile = ""
exit 1
else
redim preserve $ReadFile[$i]
exit 0
endif
EndFunction

; will load the contents of a text file into an array with WScript
Function loadfile($file)
DIM $, $fso,$f,$fs
$fso = CreateObject("Scripting.FileSystemObject")
$f = $fso.GetFile($file)
If @ERROR Exit(2) EndIf
$fs = $f.OpenAsTextStream(1)
$loadfile = Split($fs.Read($f.size),@CRLF)
$ = $f.Close
Exit(@ERROR)
EndFunction



the results (in ms) are :
Code:
Loadfile() = 961       constant increment ReadFile(1) = 1482        variable increment ReadFile(1) = 651
Loadfile() = 1042 constant increment ReadFile(2) = 1372 variable increment ReadFile(2) = 671
Loadfile() = 1091 constant increment ReadFile(4) = 1282 variable increment ReadFile(4) = 671
Loadfile() = 1142 constant increment ReadFile(8) = 1201 variable increment ReadFile(8) = 691
Loadfile() = 1232 constant increment ReadFile(16) = 1122 variable increment ReadFile(16) = 741
Loadfile() = 1272 constant increment ReadFile(32) = 1191 variable increment ReadFile(32) = 731
Loadfile() = 1262 constant increment ReadFile(64) = 1042 variable increment ReadFile(64) = 741
Loadfile() = 1262 constant increment ReadFile(128) = 961 variable increment ReadFile(128) = 761
Loadfile() = 1272 constant increment ReadFile(256) = 821 variable increment ReadFile(256) = 731
Loadfile() = 1352 constant increment ReadFile(512) = 791 variable increment ReadFile(512) = 741
Loadfile() = 1292 constant increment ReadFile(1024) = 771 variable increment ReadFile(1024) = 731
Loadfile() = 1282 constant increment ReadFile(2048) = 751 variable increment ReadFile(2048) = 741
Loadfile() = 1242 constant increment ReadFile(4096) = 801 variable increment ReadFile(4096) = 761
Loadfile() = 1342 constant increment ReadFile(8192) = 842 variable increment ReadFile(8192) = 761



it's surprising because time for LoadFile should be constant and it is not.

"constant increment" means that when i redim an array, i add a constant value to the current size.
"variable increment" means that when i redim an array, i add a value to the current size and then, i multiply this value by 2 for the next resizing.

I am working on a Pentium IV 2 Mhz with 512 MB.
The OS is Windows NT 4 SP6a

PS : sorry for my english
_________________________
Christophe

Top
#131972 - 2005-01-06 05:49 PM Re: Kix script give high cpu usage
Bryce Offline
KiX Supporter
*****

Registered: 2000-02-29
Posts: 3167
Loc: Houston TX
We have 2 different readfiles here...

something is wrong with the readfile() that Christophe is using. His readfile it is not returning any information.

ok, i found the error in Chris's readfile() in line 6 in the UDF you need to change the line
Code:

Dim $ReadFile[$inc]

to

reDim $ReadFile[$inc]



after doing that... i reran his code (i changed the location of dir.txt to c:\dir.txt, also changing the CI and VI stuff to better fit the screen).

Processor: Intel(R) Pentium(R) 4 CPU 2.66GHz
Memory: 510MB RAM



Code:

getfilesize(c:\dir.txt)=7725170
Loadfile() = 2391 CI ReadFile(1) = 6890 VI ReadFile(1) = 2781
Loadfile() = 2766 CI ReadFile(2) = 6578 VI ReadFile(2) = 2922
Loadfile() = 2844 CI ReadFile(4) = 6265 VI ReadFile(4) = 2969
Loadfile() = 2875 CI ReadFile(8) = 6125 VI ReadFile(8) = 2953
Loadfile() = 2922 CI ReadFile(16) = 6078 VI ReadFile(16) = 3078
Loadfile() = 2907 CI ReadFile(32) = 6015 VI ReadFile(32) = 3016
Loadfile() = 2891 CI ReadFile(64) = 5984 VI ReadFile(64) = 3031
Loadfile() = 2906 CI ReadFile(128) = 6157 VI ReadFile(128) = 3109
Loadfile() = 2891 CI ReadFile(256) = 6093 VI ReadFile(256) = 3141
Loadfile() = 2938 CI ReadFile(512) = 4640 VI ReadFile(512) = 3094
Loadfile() = 2906 CI ReadFile(1024) = 3781 VI ReadFile(1024) = 3094
Loadfile() = 2891 CI ReadFile(2048) = 3453 VI ReadFile(2048) = 3141
Loadfile() = 2906 CI ReadFile(4096) = 3297 VI ReadFile(4096) = 3125
Loadfile() = 2968 CI ReadFile(8192) = 3172 VI ReadFile(8192) = 3110




Bryce


Top
#131973 - 2005-01-07 01:16 AM Re: Kix script give high cpu usage
NTDOC Administrator Offline
Administrator
*****

Registered: 2000-07-28
Posts: 11625
Loc: CA
Well after testing with Bryce on multiple different file size and different array sizes and looping only one method at a time and both at the same time, etc...

The FSO method is only about .07 seconds faster on average for a file size around 800K but is just about 1 second faster for a file size of 8MB then using the Variable Incremental method in ReadFile() by Christophe Melin above. The Constant method is quite slow in comparison.

In general for a single run script on a small file probably no real difference. However if you need to run something on a large file or many files all day long then the FSO method will be faster by the end of the day.

Top
#131974 - 2005-01-07 10:06 AM Re: Kix script give high cpu usage
Richard H. Administrator Offline
Administrator
*****

Registered: 2000-01-24
Posts: 4946
Loc: Leatherhead, Surrey, UK
Don't forget however that creating the array by whichever method is an overhead.

The array will be returned to the main script which will need to iterate it to do the real work.

Moving the file read into the main script rather than using a UDF will avoid the overhead in both CPU and memory - the cost of maintaining an additional 8MB local variable data in memory should not be taken lightly!

It is a balance in the end of course.

As a one-off admin task the simplicity and ease of using one of these UDFs far outweighs the disadvantages.

Should you be writing a user activated script to be deployed on (say) multi-user Citrix or Terminal Server environments you would be more conservative about how resources are used.

Top
Page 1 of 1 1


Moderator:  Jochen, Allen, Radimus, Glenn Barnas, ShaneEP, Ruud van Velsen, Arend_, Mart 
Hop to:
Shout Box

Who's Online
0 registered and 323 anonymous users online.
Newest Members
Audio, Hoschi, Comet, rrosell, PatrickPinto
17880 Registered Users

Generated in 0.108 seconds in which 0.062 seconds were spent on a total of 12 queries. Zlib compression enabled.

Search the board with:
superb Board Search
or try with google:
Google
Web kixtart.org