Why does SET performance degrade as environment size grows?

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
Aacini
Expert
Posts: 1611
Joined: 06 Dec 2011 22:15
Location: México City, México

Re: Why does SET performance degrade as environment size gro

#16 Post by Aacini » 01 Nov 2012 11:57

dbenham wrote:Question - Does anyone have any better insight as to why SET degrades linearly as the environment grows :?:

On 11 Dec 2011 Aacini wrote:The two main factors that affect the performance of SET command are the necessity for move the environment to another place in order to expand it, and the size of the memory blocks that must be moved in order to keep the variables alphabetically ordered.

viewtopic.php?f=3&t=2597&p=12035#p12035

Liviu wrote:As you guessed, the environment is indeed stored in contiguous memory. Also, the list is stored in sorted order, so each insertion causes a search-and-shift-to-make-room. I believe the latter is the dominant factor in the linear slowdown (since I guess the memory block is allocated with some granularity, possibly 4KB pages, so not every new variable would trigger a reallocation).
Liviu


:?:

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Why does SET performance degrade as environment size gro

#17 Post by Liviu » 01 Nov 2012 12:21

Aacini wrote: :?:

Sorry, didn't mean to steal undue credit, it's just been too long a thread ;-)

That said, the page I linked provides an authoritative reference on the topic. It also makes clear that all environment is stored in one single contiguous memory block, and the internal format explains why variable names can't contain "=" signs, and why \0 nul characters can't be embedded in either name or value.

Liviu

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Why does SET performance degrade as environment size gro

#18 Post by Ed Dyreen » 01 Nov 2012 12:31

Liviu wrote:It also makes clear that all environment is stored in one single contiguous memory block.
One contigious block, and how does it keeps different local scopes apart :?:

Code: Select all

performance at 100%
set var1=value
performance at 90%
setlocal
    performance at 90%
    set var2=value
    set var3=value
    performance at 70%
    set var3=null
    performance at 80% ( actually a bit higher as Aacini's shown )
    set var2=null
    set var1=null
    performance at 90%
endlocal
performance at 90%
Naively I thought I could get close to a 100% inside setlocal :|

Aacini
Expert
Posts: 1611
Joined: 06 Dec 2011 22:15
Location: México City, México

Re: Why does SET performance degrade as environment size gro

#19 Post by Aacini » 01 Nov 2012 16:12

Liviu wrote:That said, the page I linked provides an authoritative reference on the topic. It also makes clear that all environment is stored in one single contiguous memory block,
Aacini wrote:... the internal operation of SET VAR=VALUE command follow these steps:

  • When a new variable is defined with a value that exceed the current environment size, the environment is copied to a new area if the area beyond it is not available.


Liviu wrote:and the internal format explains why variable names can't contain "=" signs, and why \0 nul characters can't be embedded in either name or value.
On 21 Jan 2012 Aacini wrote:Batch variables are stored in the Environment (a memory block of up to 32 MB long) as strings with this format: VARNAME=VARVALUE0; a byte with binary zero mark the variable end followed by the next variable, and a second zero mark the Environment end. CMD.EXE have a limit of 8 KB when it search the Environment for variable names/values. In conclusion, the maximum VALUE length for 1-letter named variables is 8189 bytes.

viewtopic.php?f=3&t=2828&p=12965#p12965




Ed Dyreen wrote:One contigious block, and how does it keeps different local scopes apart :?:

(Hi Ed, thanks for your welcome in the other topic! :) )

Each environment is a single contiguous memory block. SETLOCAL command duplicate (reserve space and copy) current environment into another memory area, but only for the used portion of the current environment. For this reason I suggested the use of :AllocateEnvironmentSpace to reserve space in the main program, and :FreeEnvironmentSpace to free reserved space after SETLOCAL command in the subroutines.

Antonio

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Why does SET performance degrade as environment size gro

#20 Post by Ed Dyreen » 01 Nov 2012 16:45

Aacini wrote:(Hi Ed, thanks for your welcome in the other topic! :) )
Sorry I'm dutch, with my limited comprehension of the english language, which other topic ?
Aacini wrote:Each environment is a single contiguous memory block. SETLOCAL command duplicate (reserve space and copy) current environment into another memory area, but only for the used portion of the current environment. For this reason I suggested the use of :AllocateEnvironmentSpace to reserve space in the main program, and :FreeEnvironmentSpace to free reserved space after SETLOCAL command in the subroutines.
Which is what I did, first I load an enormous amount of variables, then I setlocal, then I unset all variables that were loaded previously.
But speeds of this new "empty" contigious block, are still severly affected by variables loaded before setlocal.
If each environment is a single contiguous memory block then why they affect each other :?:

Aacini
Expert
Posts: 1611
Joined: 06 Dec 2011 22:15
Location: México City, México

Re: Why does SET performance degrade as environment size gro

#21 Post by Aacini » 01 Nov 2012 17:20

Ed Dyreen wrote:
Aacini wrote:(Hi Ed, thanks for your welcome in the other topic! :) )
Sorry I'm dutch, with my limited comprehension of the english language, which other topic ?

Ed Dyreen wrote:Hi Aacini, it's been a while... :)
viewtopic.php?f=3&t=3866&p=21352#p21352


Ed Dyreen wrote:Which is what I did, first I load an enormous amount of variables, then I setlocal, then I unset all variables that were loaded previously.
But speeds of this new "empty" contigious block, are still severly affected by variables loaded before setlocal.
If each environment is a single contiguous memory block then why they affect each other :?:

The only explanation is the position of the new or modified variables into the alphabetical list of existent variables. If you define a new variable that must be inserted at beginning of the environment (ie: SET A=1), all variables after it must be moved. If you define a new variable that will be appended at environment end (ie: SET ZZZZZZZZZZZ=1), the definition is immediate.

Try to name variables that changes frequently towards environment end (ZZZZ) and static variables to beginning (A).

Antonio

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Why does SET performance degrade as environment size gro

#22 Post by Liviu » 01 Nov 2012 17:25

Aacini wrote:
Liviu wrote:That said, the page I linked provides an authoritative reference on the topic. It also makes clear that all environment is stored in one single contiguous memory block,
Aacini wrote:... the internal operation of SET VAR=VALUE command follow these steps:

  • When a new variable is defined with a value that exceed the current environment size, the environment is copied to a new area if the area beyond it is not available.

Your quote in the original post started with "Let's suppose that ...". The link I gave simply confirms your supposition to be right. With all due respect, it's still useful (and more reassuring) when such information can be traced back to the root source, in this case the OS documentation.

Aacini wrote:
On 21 Jan 2012 Aacini wrote:Batch variables are stored in the Environment (a memory block of up to 32 MB long) as strings with this format: VARNAME=VARVALUE0; a byte with binary zero mark the variable end followed by the next variable, and a second zero mark the Environment end. CMD.EXE have a limit of 8 KB when it search the Environment for variable names/values. In conclusion, the maximum VALUE length for 1-letter named variables is 8189 bytes.

Not sure where the 32MB number comes from - it was 32KB in XP, and unlimited in Vista/Win7 (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx). Other than that, you are correct, with only observation that while CMD has indeed a lower 8KB variable limit, the OS itself has a 32KB per value limit which applies to all processes in Windows.

Ed Dyreen wrote:Naively I thought I could get close to a 100% inside setlocal

At face value, you are getting the same performance numbers before/after endlocal as right before/after setlocal. Guess you didn't expect something to run faster just because it entered a setlocal block, so I am probably missing some background on what exactly you are running, and what those timings measure.

Liviu

Aacini
Expert
Posts: 1611
Joined: 06 Dec 2011 22:15
Location: México City, México

Re: Why does SET performance degrade as environment size gro

#23 Post by Aacini » 01 Nov 2012 19:26

Liviu wrote:
Aacini wrote:
On 21 Jan 2012 Aacini wrote:Batch variables are stored in the Environment (a memory block of up to 32 MB long)...

Not sure where the 32MB number comes from - it was 32KB in XP, and unlimited in Vista/Win7. Other than that, you are correct...

Liviu

Could be possible that the page on OS documentation (with "authoritative reference on the topic") that you give us be wrong? :shock:

At this site: Microsoft Windows XP - Command shell overview, under "Setting environment variables, Note" said:
  • The maximum individual environment variable size is 8192bytes.
  • The maximum total environment variable size for all variables, which includes variable names and the equal sign, is 65,536KB.
It is funny that you have not realized that this topic is precisely about the problems to manage large environments and that all Batch programs listed here use environments up to 1293KB size (this data first appear in line # 14 of this topic). If the 32KB limit be true, these programs just did not run!

Antonio

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Why does SET performance degrade as environment size gro

#24 Post by Ed Dyreen » 01 Nov 2012 20:06

Liviu wrote:Not sure where the 32MB number comes from - it was 32KB in XP, and unlimited in Vista/Win7 (http://msdn.microsoft.com/en-us/library/windows/desktop/ms682653(v=vs.85).aspx). Other than that, you are correct, with only observation that while CMD has indeed a lower 8KB variable limit, the OS itself has a 32KB per value limit which applies to all processes in Windows.
The limit is 64MB for XP, I've went well over 32MB many times.
Apart from performance degradation, another side effect of large environments is many installers/programs will start to fail to initialize, for example wmic.EXE.
This may no longer be the case on newer OSes if they indeed have no memory limit.

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Why does SET performance degrade as environment size gro

#25 Post by Liviu » 02 Nov 2012 19:10

Aacini wrote:Could be possible that the page on OS documentation (with "authoritative reference on the topic") that you give us be wrong? :shock:

Guess it's possible, since said documentation is wrong, indeed.

At least, it's wrong at face value. The lower 32K limit might apply to, or cover, some corner case that's not obvious outright. One possible such case (from a response to another post quoting the same figure) is mentioned at http://blogs.msdn.com/b/oldnewthing/archive/2010/02/03/9957320.aspx#9957646: "This isn't true (on XP at least), though it is what all the documentation says. You can create megabytes of environment block and successfully pass it to a child process. As far as I can tell, the 32K limit only applies if an environment block is converted from ANSI to UNICODE in CreateProcess."

Aacini wrote:Batch variables are stored in the Environment (a memory block of up to 32 MB long)...
Aacini wrote:At this site: Microsoft Windows XP - Command shell overview, under "Setting environment variables, Note" said:
  • The maximum individual environment variable size is 8192bytes.
  • The maximum total environment variable size for all variables, which includes variable names and the equal sign, is 65,536KB.
Ed Dyreen wrote:The limit is 64MB for XP

Once bitten, twice shy ;-) Sorry, but I don't see either 32M or 64M limit in XP Sp3.

Code: Select all

C:\tmp>for /l %n in (1111048576,1,1111114765) do @set __%n_%n=%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n%n

C:\tmp>set >env.txt

C:\tmp>cmd

C:\tmp>set >env-copy.txt

C:\tmp>exit

C:\tmp>cmd /u

C:\tmp>set >env-copy-u.txt

C:\tmp>exit

C:\tmp>dir env*.txt

11/02/2012  06:28 PM       135,825,408 env-copy-u.txt
11/02/2012  06:28 PM        67,912,704 env-copy.txt
11/02/2012  06:27 PM        67,912,704 env.txt

C:\tmp>find /c /v "" <"env.txt"
66243

C:\tmp>find /c /v "" <"env-copy.txt"
66243

C:\tmp>find /c /v "" <"env-copy-u.txt"
66243

C:\tmp>fc /b env.txt env-copy.txt
Comparing files env.txt and ENV-COPY.TXT
FC: no differences encountered

C:\tmp>

The test case above adds 1K-long lines to the environment in a loop, totaling more than 64M characters (= 128MB memory block size, since the environment is stored as Unicode). The actual memory size is slightly lower than the byte count on disk (because line ends take one NUL char in memory vs 2 CR+LF on disk), but still easily over 64M characters. It looks to be working fine, including being successfully copied over to a child cmd process. This seems to debunk the 64M limit, regardless of it being meant as bytes or characters.

Liviu

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Why does SET performance degrade as environment size gro

#26 Post by Ed Dyreen » 03 Nov 2012 03:24

Liviu wrote:Sorry, but I don't see either 32M or 64M limit in XP Sp3.
It's a little off-topic so won't go any further.
Wikipedia said in a document which I can't find or no longer exists.. XP has a 64MB limit for executables.
I've always assumed that would apply for cmd.exe but I've never tested it.
What I do know is that wmic.EXE simply won't run at a certain value well below this limit.
But then I rarely test anything, I just observe and assume.

alan_b
Expert
Posts: 357
Joined: 04 Oct 2008 09:49

Re: Why does SET performance degrade as environment size gro

#27 Post by alan_b » 03 Nov 2012 03:53

Ed Dyreen wrote:
Liviu wrote:Sorry, but I don't see either 32M or 64M limit in XP Sp3.

Wikipedia said in a document which I can't find or no longer exists.. XP has a 64MB limit for executables.

I cannot see how executables are related to environmental space.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Why does SET performance degrade as environment size gro

#28 Post by Ed Dyreen » 03 Nov 2012 04:47

alan_b wrote:I cannot see how executables are related to environmental space.
They are related in that every program can write to- or read from it and pass it on to their child processes.
Unlike Linux, windows programs usually depend on it being correctly initialized.
http://www.dostips.com/forum/viewtopic.php?p=9361#p9361

einstein1969
Expert
Posts: 763
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Why does SET performance degrade as environment size gro

#29 Post by einstein1969 » 11 Oct 2013 05:46

Hi to all,

recently i have a problem of performance with a batch. I read this thread and i perform some test for understand why my code is so slow.

But I realized shortly and i need help. The question is on SET, SET /A, EXPAND.

I have tried to perform test in some env for understand. There are 3 env type, where i changed the variable name and the size.
But i have mantain the size of the env.

Why the time of expand change though the size of env remain costant?
There are parameters to be taken into cosider in the choice of the composition of the name of the variables?
As affects the size of the variables, and then the number of the same?

I tried to apply the trick of Aacini to see if it would improve my sets but I have not been successful. Why?

Env 1: (original ambient)

Code: Select all

 [  8:04:32 -  8:24:29 ] Reseved Space : 0KB   Loop : 1000
 ---------------------------------------------------------------------------
 GROW_test_________:   0.00   0.00   0.02   0.04   0.17   0.75   2.92  12.17
 ENV_SIZE__________:    4KB   16KB   36KB   77KB  158KB  320KB  643KB 1290KB
 base______________:   0.02   0.00   0.01   0.00   0.00   0.02   0.01   0.03
 SL_EL_____________:   0.30   0.50   1.73   2.75   5.76  13.70  27.05  53.84
 SET_SL_S_EL_a_____:   0.03   0.18   0.45   0.84   1.88   5.02   9.86  20.04
 UNSET_SL_U_EL_a___:   0.01   0.14   0.04   0.81   2.10   4.97   9.94  19.85
 SET_SL_S_EL_zzz___:   0.04   0.18   0.10   1.20   2.18   6.43  11.55  23.85
 UNSET_SL_U_EL_zzz_:   0.01   0.15   0.50   0.80   1.64   4.75   9.51  18.97
 EXPAND_a__________:   0.12   0.14   0.13   0.14   0.14   0.13   0.14   0.12
 EXPAND_zzz________:   0.13   0.18   0.21   0.30   0.47   0.85   1.43   2.53
 SET_UNSET_zzz_____:   0.12   0.32   1.07   2.03   4.04  10.92  21.27  42.53
 SET_UNSET_a_______:   0.12   0.33   0.93   2.03   4.42  10.86  21.23  43.04
 SET_a_____________:   0.04   0.14   0.40   0.86   1.96   4.55   8.80  17.72
 SET_zzz___________:   0.04   0.15   0.44   0.94   2.07   4.71   9.40  18.83
 UNSET_a___________:   0.04   0.16   0.45   0.95   2.06   4.73   9.39  18.95
 UNSET_zzz_________:   0.05   0.16   0.44   0.95   2.08   4.70   9.42  18.89
 _2EXP_SET_A_pal___:   0.09   0.19   0.49   0.97   2.05   4.55   8.92  17.72
 _2EXP_SET_pal_____:   0.08   0.16   0.45   0.93   2.01   4.50   8.92  17.86
 _EXP_pal__________:   0.14   0.14   0.14   0.16   0.14   0.14   0.16   0.15 <---- NOTE THIS
 _EXP_SET_pal______:   0.08   0.16   0.45   0.95   2.03   4.53   8.89  17.64
 _EXP_SET_A_pal____:   0.07   0.18   0.45   0.95   2.01   4.56   8.90  17.81
 IF_SET_3EXP_pal___:   0.03   0.05   0.10   0.17   0.28   0.61   1.17   2.31
 EXP_TIME__________:   0.15   0.19   0.20   0.28   0.44   0.84   1.46   2.54
 EXP_RND___________:   0.16   0.17   0.21   0.26   0.43   0.85   1.41   2.52


Env 2: (my batch env)

Code: Select all

 [  8:24:36 -  9:15:52 ] Reseved Space : 0KB   Loop : 1000
 ---------------------------------------------------------------------------
 GROW_A1___________:   0.00   0.14   0.83   4.13  17.12  73.37 308.76 250.84
 ENV_SIZE__________:    5KB   16KB   36KB   76KB  157KB  323KB  656KB 1326KB
 base______________:   0.00   0.00   0.00   0.00   0.00   0.02   0.03   0.03
 SL_EL_____________:   0.33   0.56   1.14   2.94   6.08  14.55  29.89  60.86
 SET_SL_S_EL_a_____:   0.06   0.14   0.74   0.84   2.78   5.09  10.61  21.71
 UNSET_SL_U_EL_a___:   0.03   0.15   0.74   1.00   1.92   5.02  10.47  21.18
 SET_SL_S_EL_zzz___:   0.02   0.19   0.66   1.40   2.31   6.06  12.72  26.67
 UNSET_SL_U_EL_zzz_:   0.01   0.16   0.39   0.88   2.05   4.98  10.36  20.50
 EXPAND_a__________:   0.15   0.14   0.14   0.14   0.14   0.13   0.13   0.14
 EXPAND_zzz________:   0.15   0.19   0.28   0.40   0.72   1.45   2.64   5.04
 SET_UNSET_zzz_____:   0.15   0.34   0.94   2.01   4.34  11.15  23.01  47.14
 SET_UNSET_a_______:   0.17   0.36   0.99   2.22   4.70  11.13  22.89  47.52
 SET_a_____________:   0.08   0.16   0.43   0.91   2.00   4.62   9.48  19.41
 SET_zzz___________:   0.08   0.17   0.48   1.01   2.18   5.12  10.29  21.11
 UNSET_a___________:   0.08   0.17   0.49   1.03   2.22   5.03  10.36  21.04
 UNSET_zzz_________:   0.10   0.17   0.37   1.01   2.21   5.03  10.29  21.08
 _2EXP_SET_A_pal___:   0.13   0.33   0.48   1.77   5.16   6.08  16.30  39.64
 _2EXP_SET_pal_____:   0.07   0.18   0.45   1.11   2.70   4.92  10.82  23.20
 _EXP_pal__________:   0.15   0.16   0.15   0.30   0.76   0.41   1.67   4.59 <---- NOTE THIS
 _EXP_SET_pal______:   0.10   0.20   0.36   1.09   2.66   4.94  10.79  23.48
 _EXP_SET_A_pal____:   0.11   0.30   0.56   1.70   5.19   6.03  16.28  39.80
 IF_SET_3EXP_pal___:   0.11   0.18   0.34   0.93   2.03   4.66   9.49  19.56
 EXP_TIME__________:   0.15   0.18   0.27   0.41   0.72   1.45   2.66   5.07
 EXP_RND___________:   0.15   0.19   0.25   0.41   0.71   1.42   2.63   5.03


Env 3 (simil Env 2) :

Code: Select all

 [  9:16:01 - 10:09:32 ] Reseved Space : 0KB   Loop : 1000
 ---------------------------------------------------------------------------
 GROW_A2___________:   0.00   0.16   0.83   4.00  17.16  72.64 314.66 271.93
 ENV_SIZE__________:    5KB   16KB   36KB   76KB  156KB  323KB  656KB 1326KB
 base______________:   0.01   0.00   0.00   0.00   0.00   0.02   0.01   0.03
 SL_EL_____________:   0.32   0.53   1.14   3.05   6.13  14.54  29.86  60.62
 SET_SL_S_EL_a_____:   0.04   0.19   0.37   0.78   1.96   5.04  10.57  21.62
 UNSET_SL_U_EL_a___:   0.03   0.17   0.36   0.79   1.93   5.09  10.55  21.52
 SET_SL_S_EL_zzz___:   0.03   0.22   0.96   1.50   2.20   5.96  12.58  25.82
 UNSET_SL_U_EL_zzz_:   0.03   0.19   0.79   1.17   1.82   5.03  10.26  20.89
 EXPAND_a__________:   0.13   0.14   0.14   0.15   0.14   0.12   0.15   0.12
 EXPAND_zzz________:   0.15   0.21   0.27   0.39   0.69   1.35   2.49   4.74
 SET_UNSET_zzz_____:   0.14   0.33   0.98   2.45   4.28  11.07  22.77  46.31
 SET_UNSET_a_______:   0.14   0.36   0.78   1.66   4.62  11.02  22.85  46.91
 SET_a_____________:   0.06   0.14   0.32   0.66   2.02   4.59   9.45  19.36
 SET_zzz___________:   0.07   0.17   0.35   0.76   2.17   4.92  10.18  20.72
 UNSET_a___________:   0.07   0.17   0.47   0.75   2.19   5.00  10.32  20.75
 UNSET_zzz_________:   0.07   0.18   0.36   0.75   2.17   4.97  10.24  20.78
 _2EXP_SET_A_pal___:   0.13   0.53   1.43   3.02   7.22  14.41  30.07  62.09
 _2EXP_SET_pal_____:   0.10   0.21   0.48   1.07   2.78   6.19  12.72  25.82
 _EXP_pal__________:   0.14   0.18   0.28   0.50   0.95   1.87   3.69   7.42 <---- NOTE THIS why is so different from previus?
 _EXP_SET_pal______:   0.09   0.22   0.49   1.06   2.86   6.25  12.81  25.94
 _EXP_SET_A_pal____:   0.12   0.46   1.23   2.59   6.44  12.70  26.71  55.62
 IF_SET_3EXP_pal___:   0.11   0.24   0.66   1.09   2.95   6.47  13.26  26.97
 EXP_TIME__________:   0.18   0.19   0.26   0.39   0.66   1.36   2.47   4.71
 EXP_RND___________:   0.16   0.19   0.25   0.39   0.66   1.35   2.45   4.69



The code (Hoping not to have made ​​too many mistakes ...) A little long, but I did not know how to shorten it:

Code: Select all

@echo off
setlocal enableDelayedExpansion

rem for graph
rem mode con: cols=100 lines=52

set /a alt=0, aRes=0
for %%p in (%1 %2) do (   if /I "%%p"=="-R" call :ReserveEnvironmentSpace 1400
         if /I "%%p"=="-A1" set "alt=1"
         if /I "%%p"=="-A2" set "alt=2" )

set "test=a"
for /l %%n in (1 1 10) do set "test=!test!!test!"
set buf1=%test%
set buf2=%test%
set "buf3=a"
for /l %%n in (1 1 9) do set "buf3=!buf3!!buf3!"
set cnt=0
set "a=a"
set "zzz=a"
set "aaa=a"

rem pre-alloc
if "%3"=="" (set prec=1000) else set prec=%3
set /a af=0, at=prec, env_size=0, att=0, aval=0, aRows=0, ai=0, cnt2=0, arange=0, acs=0, alg=0
set "a0=%time%"
set "a1=%time%"
set "aLis= "

goto :Pre_!alt!
:Pre_1
:Pre_2
  rem new env base
  set /a ai=0, dm=256*256*3 & for %%c in (000000 000080 008000 008080 800000 800080 808000 C0C0C0 808080 0000FF 00FF00 00FFFF FF0000 FF00FF FFFF00 FFFFFF) do (set "p16[!ai!]=%%c" & set /a ai=ai+1)
  for /L %%i in (0,1,15) do set /a "rgb=0x!p16[%%i]!, rr[%%i]=rgb >> 16, gg[%%i]=(rgb >> 8) & 0xFF, bb[%%i]=rgb & 0xFF"

:Pre_0

set ag0=%time%
for %%n in (0 10 20 40 80 160 320 640) do call :test %%n

cls & call :st
call :st >> test_env.out.!aRes!_!alt!_!prec!.txt
echo > test_env.exit
pause
exit /b


:test

goto :Grow_!alt!

:Grow_2

  rem tuned for 0 10 20 40 80 160 ....
  set /a "af=cnt+1, at=cnt+%1*8+(%1*6/10)"
  set "a0=%time%"
  for /L %%i in (%af%,1,%at%) do (
     set /a "pal16_4.R[%%i]=!random! %% 256, pal16_4.G[%%i]=!random! %% 256, pal16_4.B[%%i]=!random! %% 256"
   set "pal16_4.bg[%%i]=9" & set "pal16_4.fg[%%i]=D" & set "pal16_4.char[%%i]=±"
   if !random! lss 2048 (set /a "i=(%%i-af)*1000/(at-af+1)"&set i=00!i!&title GROW: !i:~-3,2!.!i:~-1!%%  !time:~0,8!)
  )
  set "a1=%time%"
  set /a "cnt=cnt+%1*8+(%1*6/10)" & title
  call :stuffed a0 a1 GROW_A2 0

  goto :env

:Grow_1

  set /a "af=cnt+1, at=cnt+%1*8+(%1*6/10)"
  set "a0=%time%"
  for /L %%i in (%af%,1,%at%) do (
     set /a "pal16_4[%%i].R=!random! %% 256, pal16_4[%%i].G=!random! %% 256, pal16_4[%%i].B=!random! %% 256"
   set "pal16_4[%%i].bg=9" & set "pal16_4[%%i].fg=D" & set "pal16_4[%%i].char=±"
   if !random! lss 2048 (set /a "i=(%%i-af)*1000/(at-af+1)"&set i=00!i!&title GROW: !i:~-3,2!.!i:~-1!%%  !time:~0,8!)
  )
  set "a1=%time%"
  set /a "cnt=cnt+%1*8+(%1*6/10)" & title
  call :stuffed a0 a1 GROW_A1 0
  goto :env

:Grow_0
  set /a "af=cnt+1, at=cnt+%1"
  set "a0=%time%"
  for /l %%n in (%af% 1 %at%) do (
    set test%%n=%test%
  )
  set "a1=%time%"
  set /a "cnt=cnt+%1"
  call :stuffed a0 a1 GROW_test 0

:env
  set >env_!aRes!_!alt!_!prec!_%1.txt
  for %%f in (env_!aRes!_!alt!_!prec!_%1.txt) do set /a "env_size=(%%~zf >> 10)
  set "env_size=      %env_size%KB"
  set "env_size=%env_size:~-6%"
  set A_ENV_SIZE__________=%A_ENV_SIZE__________% %env_size%
  if "!aLis:ENV_SIZE__________=!"=="!aLis!" set "aLis=!aLis! ENV_SIZE__________"

set /a "af=1, at=prec"
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
)
set "a1=%time%"
call :stuffed a0 a1 base 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  setlocal
  endlocal
)
set "a1=%time%"
call :stuffed a0 a1 SL_EL base

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  setlocal
  set "a=b"
  endlocal
)
set "a1=%time%"
call :stuffed a0 a1 SET_SL_S_EL_a "SL_EL+base"

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  setlocal
  set "a="
  endlocal
)
set "a1=%time%"
call :stuffed a0 a1 UNSET_SL_U_EL_a "SL_EL+base"

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  setlocal
  set "zzz=b"
  endlocal
)
set "a1=%time%"
call :stuffed a0 a1 SET_SL_S_EL_zzz "SL_EL+base"

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  setlocal
  set "zzz="
  endlocal
)
set "a1=%time%"
call :stuffed a0 a1 UNSET_SL_U_EL_zzz "SL_EL+base"

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  echo !a!>nul
)
set "a1=%time%"
call :stuffed a0 a1 EXPAND_a base

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  echo !zzz!>nul
)
set "a1=%time%"
call :stuffed a0 a1 EXPAND_zzz base

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  set "zzz=b"
  set "zzz="
)
set "a1=%time%"
call :stuffed a0 a1 SET_UNSET_zzz base

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  set "a=b"
  set "a="
)
set "a1=%time%"
call :stuffed a0 a1 SET_UNSET_a base

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  set "a=b"
)
set "a1=%time%"
call :stuffed a0 a1 SET_a base

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  set "zzz=b"
)
set "a1=%time%"
call :stuffed a0 a1 SET_zzz base

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  set "a="
)
set "a1=%time%"
call :stuffed a0 a1 UNSET_a base

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
  rem
  set "zzz="
)
set "a1=%time%"
call :stuffed a0 a1 UNSET_zzz base

set /a cnt2=cnt2+(%1*8+(%1*6/10)), pal16_4.size=cnt2/2
rem echo !pal16_4.size! & pause

goto :alt_m_!alt!

:alt_m_0

if "!alt!" equ "0" For %%i in (!pal16_4.size!) do set /a "pal16_4[%%i].R=%random% %% 256, pal16_4[%%i].G=%random% %% 256, pal16_4[%%i].B=%random% %%256"

:alt_m_1

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4[!pal16_4.size!].R"
)
set "a1=%time%"
call :stuffed a0 a1 _2EXP_SET_A_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4[%pal16_4.size%].R!"
)
set "a1=%time%"
call :stuffed a0 a1 _2EXP_SET_pal 0

goto :alt_m_0-1_!pal16_4.size!

:alt_m_0-1_0
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4[0].R!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4[0].R!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4[0].R"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_0-1_43
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4[43].R!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4[43].R!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4[43].R"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_0-1_129
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4[129].R!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4[129].R!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4[129].R"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_0-1_301
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4[301].R!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4[301].R!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4[301].R"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_0-1_645
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4[645].R!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4[645].R!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4[645].R"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_0-1_1333
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4[1333].R!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4[1333].R!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4[1333].R"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_0-1_2709
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4[2709].R!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4[2709].R!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4[2709].R"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_0-1_5461
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4[5461].R!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4[5461].R!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4[5461].R"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_2

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4.R[!pal16_4.size!]"
)
set "a1=%time%"
call :stuffed a0 a1 _2EXP_SET_A_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4.R[%pal16_4.size%]!"
)
set "a1=%time%"
call :stuffed a0 a1 _2EXP_SET_pal 0

goto :alt_m_2_!pal16_4.size!

:alt_m_2_0
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4.R[0]!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4.R[0]!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4.R[0]"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_2_43
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4.R[43]!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4.R[43]!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4.R[43]"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_2_129
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4.R[129]!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4.R[129]!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4.R[129]"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_2_301
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4.R[301]!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4.R[301]!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4.R[301]"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_2_645
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4.R[645]!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4.R[645]!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4.R[645]"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_2_1333
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4.R[1333]!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4.R[1333]!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4.R[1333]"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_2_2709
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4.R[2709]!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4.R[2709]!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4.R[2709]"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:alt_m_2_5461
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !pal16_4.R[5461]!> nul
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set "a=!pal16_4.R[5461]!"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   set /a "a=pal16_4.R[5461]"
)
set "a1=%time%"
call :stuffed a0 a1 _EXP_SET_A_pal 0
goto :_fi_set

:_fi_set
set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   if !dm! gtr !a! set ind=!pal16_4.size!
)
set "a1=%time%"
call :stuffed a0 a1 IF_SET_3EXP_pal 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !time!> nul
)
set "a1=%time%"
call :stuffed a0 a1 EXP_TIME 0

set "a0=%time%"
for /l %%n in (%af% 1 %at%) do (
   echo !random!> nul
)
set "a1=%time%"
call :stuffed a0 a1 EXP_RND 0

rem call :graph

rem del env.txt
exit /b

:graph

set /a ALiB=0, ac=0, Cols=7, aval=aval+1

set "Ai_= " & For /F %%l in ('set Ai_') do set "%%l"

for %%L in (!aLis!) do if not "%%L"=="ENV_SIZE__________" if not "%%L"=="base______________" (
   set /a arange=!max_%%L!-!min_%%L!, Ali=1
   if !arange! lss 0 set /a arange=-arange
   set "alg=%%L             "
   set alg=!alg:~0,13!
   for %%v in (!ALiB!) do set "Ai_%%v=!Ai_%%v! !alg!"
   for %%R in (!LRAW_%%L!) do (
      if !arange! gtr 5 (set /a "att=(%%R-!min_%%L!)*12/arange-1") else set att=5
      set "acs="
      For /L %%c in (0,1,!att!) do set "acs=!acs!-" & rem |
      set "acs=!acs!o             "
      set acs=!acs:~0,13!
      set /a ai=Ali+ALiB
      for %%v in (!ai!) do set "Ai_%%v=!Ai_%%v! !acs!"
      set /a Ali=Ali+1
   )
   set /a "ac=(ac+1) %% cols"
   if  !ac! equ 0 set /a "ALiB=ALiB+(aval+1)"
)
set /a aRows=ALiB+aval
exit /b

:st
echo  [ %ag0:~0,8% - %time:~0,8% ] Reseved Space : %aRes%KB   Loop : %prec%
echo  ---------------------------------------------------------------------------
for %%L in (!aLis!) do echo  %%L:!A_%%L!
rem for graph
rem echo(
rem For /L %%L in (0,1,!aRows!) do echo(!Ai_%%L!
exit /b

:stuffed
set "att=%3__________________"
rem echo !att:~0,18! & pause
for %%L in ("!att:~0,18!") do (
   if "!aLis:%%~L=!"=="!aLis!" set "aLis=!aLis! %%~L"
   call :diffTimeRaw %1 %2 %3
   set /a "%3=%3-(%~4)"
   if !%3! lss 0 set %3=0
   set a0=!%3!
   rem for graph
   rem if not defined min_%%~L (set /a min_%%~L=%3) else if !%3! lss !min_%%~L! set /a min_%%~L=%3
   rem if not defined max_%%~L (set /a max_%%~L=%3) else if !%3! gtr !max_%%~L! set /a max_%%~L=%3
   rem set LRAW_%%~L=!LRAW_%%~L! !a0!
   call :padNum a0
   set A_%%~L=!A_%%~L! !a0!
)
cls
call :st
exit /b

:padNum
set "%1=     !%1!"
set "%1=!%1:~-5,3!.!%1:~-2!"
set "%1=!%1:.-=-0.0!"
set "%1=!%1:-.=-0.!"
set "%1=!%1: .=0.!"
set "%1=!%1:. =.0!"
exit /b

:diffTimeRaw2 tStart tEnd result=
for /F "tokens=1-4 delims=:.," %%a in ("!%1!") do set /A tStart=((%%a*60+10%%b%%100)*60+10%%c%%100)*100+10%%d%%100
for /F "tokens=1-4 delims=:.," %%a in ("!%2!") do set /A tEnd=((%%a*60+10%%b%%100)*60+10%%c%%100)*100+10%%d%%100
set /A %3=tEnd-tStart
exit /B

:diffTimeRaw tStart tEnd result=
set aa="!%~1!:!%~2!"
for /F "tokens=1-8 delims=:.," %%a in ("!aa: =0!") do set /a "%3=(a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d)+((a>>31) & 8640000)"
exit /B


:ReserveEnvironmentSpace sizeInKB
rem Define the first large variable (reserving 6 bytes for variable name)
set aRes=%1
set z1=X
for /L %%i in (1,1,12) do set z1=!z1!!z1!
set z1=!z1!!z1:~8!
rem Define the rest of large variables
set /A lastVar=%1 / 8
for /L %%i in (2,1,%lastVar%) do set z%%i=!z1!
rem Delete all the large variables in bottom-up order
for /L %%i in (%lastVar%,-1,1) do set z%%i=
exit /B


Einstein1969

carlos
Expert
Posts: 489
Joined: 20 Aug 2010 13:57
Location: Chile
Contact:

Re: Why does SET performance degrade as environment size gro

#30 Post by carlos » 13 Feb 2014 14:09

Hello.
Using doskey for save variables is a alternative.
Someone knows where are stored this variables?
It seems to not be in a environment block.
See this post: http://www.dostips.com/forum/viewtopic.php?f=3&t=5366

Post Reply