Memory Allocation & Self Modifying Code
[1/3] from: robbo1mark:aol at: 2-Aug-2001 8:52
Memory Allocation & Self Modifying Code
This mailing will discuss some predictive theories on
REBOL Block! memory allocation and also how it effects
the result of performing some self modifying code
expressions.
DISCLAIMER:
I only had REBOL/Core 2.5 running on Windows 95 available
whilst performing these tests / enquiries so I can only
make statements about results I found in relation to this
REBOL version and platform combination, I do not know how
this compares to other REBOL versions & platforms etc.
REBOL Block! Memory Allocation.
In relation to an earlier thread this week What Kind of Bug is
This? I was intrigued as to why a self modifying REBOL expression
always appeared to make errors at the same places but not at
others.
Ladislav Mecir mentioned that this was probably due to the REBOL
implementation issues and Brian Hawley reckoned it was most likely
due to the way memory is allocated for REBOL Block! values.
This guided my thinking & enquiries, and if you wish you can repeat
my tests with the following code.
>> Echo %test.txt
>> a: [ append a [+ 1] 1]
>> loop 1000 [ print [ do a newline ] print [ "Block length: " length? a
Bytes used:
((length? a) * 16) ] ]
I ran this code until REBOL crashed at the following stage
254
Block Length: 510 Bytes Used 8160
Careful examination of Test.txt file reveals the following positions where
REBOL makes errors.
Block Length: 14 Bytes Used 224
6
Block Length: 16 Bytes Used 256
8
.....
Block Length: 28 Bytes Used 448
14
Block Length: 30 Bytes Used 480
14
Block Length: 32 Bytes Used 512
16
.....
Block Length: 28 Bytes Used 448
14
Block Length: 30 Bytes Used 480
14
Block Length: 32 Bytes Used 512
16
.....
Block length: 60 Bytes used: 960
30
Block length: 62 Bytes used: 992
30
Block length: 64 Bytes used: 1024
32
.....
Block Length: 124 Bytes Used 1984
62
Block Length: 126 Bytes Used 2016
62
Block Length: 128 Bytes Used 2048
64
.....
Block Length: 252 Bytes Used 4032
126
Block Length: 254 Bytes Used 4064
126
Block Length: 256 Bytes Used 4096
128
.....
Block Length: 380 Bytes Used 6080
190
Block Length: 382 Bytes Used 6112
190
Block Length: 384 Bytes Used 6144
.....
254
Block Length: 510 Bytes Used 8160
###### REBOL CRASHES HERE ##########
Now it was earlier postulated on this list
that in BLOCK! values REBOL allocates approximately
16 bytes per value. ( Or to put it another way all
REBOL values / datatypes could be contained within
a 16 byte value with pointers used to areas of
memory storage for series! type values like block!
and string! data. )
REBOL Tech staff also pointed out that users shouldn't
speculate on such things because it can be highly platform
dependant and also subject to change, which is fair enough
and true, but specualting on inner secrets of REBOL is
interesting ( well to me anyway ; ) so I'll continue.
The following code would appear to validate the theory
of approximately 16 bytes per value for Block! types.
>> a: system/stats
== 1463472
>> make block! 100000
== []
>> b: system/stats
== 3065008
>> ( b - a ) / 100000
== 16.01536
>>
So assuming that each value is ~16 bytes we can return to
the results of Test.txt and we see an interesting pattern
emerging.
REBOL Block! it would seem automatically allocates sufficient memory
to hold 16 values or 256 bytes.
The first error occurs as the evaluted block encroaches on this limit
of 16 values. The next error occurs as the evaluated block encroaches
upon 32 values, so we can infer that REBOL allocated another 256 bytes
block space in addition to the original 256 bytes.
The next errors occur at encroaching 64 , 128, 256, 384 & 512 values.
>From this I deduce that REBOL Block!'s allocate memory thus...
STAGE 1. 256 bytes or 16 values initial allocation
STAGE 2. 256 bytes or 16 values additional allocation
STAGE 3. 512 bytes or 32 values additonal allocation
STAGE 4. 1024 bytes or 64 values additional allocation
STAGE 5. 2048 bytes or 128 values each additional allocation thereafter.
If we think in terms of THE LANGUAGE THAT MUST NOT BE MENTIONED and do our
own memory allocation in a new REBOL session we see that the self modifying
block expression runs correctly without any glitches at least until it reaches
our set block! allocation limit.
Try this....
>> echo %test2.txt
>> a: make block! 1024
== []
>> insert a [append a [+ 1] 1]
== []
>> a
== [append a [+ 1] 1]
>> loop 1000 [ print [ do a newline ] print [ "Block length: " length? a
Bytes used:
((length? a) * 16) ] ]
Examining Test2.txt we see that REBOL happily & correctly evaluates away
until we get to my Block! set upper limit of 1024 values.
Block length: 1018 Bytes used: 16288
509
Block length: 1020 Bytes used: 16320
510
Block length: 1022 Bytes used: 16352
###### REBOL CRASHES HERE #############
So we can see that by utilising Memory Allocation techniques just as one
would in THE LANGUAGE WE DARE NOT MENTION IT'S NAME we can happily use
self modifying code in this manner.
Does anybody have any comments or obtain differeing results on their
appropriate REBOL version / platform combination, as I'm interested to
see how REBOL performs in those instances.
Feel free to comment here.
Cheers everybody,
Mark Dickson
[2/3] from: cyphre:volny:cz at: 2-Aug-2001 15:53
Hello Mark,
very interesting...BTW I tried your test examples on last /View running
WIN98 with the same results
regards,
Cyphre
[3/3] from: moeller_thorsten::gmx::de at: 2-Aug-2001 16:49
Hi Mark,
tried your test out with latest /view and win2k and get different results.
First test-result:
>> == [append a [+ 1] 1]
>> 1
Block length: 6 Bytes used: 96
2
Block length: 8 Bytes used: 128
3
Block length: 10 Bytes used: 160
4
Block length: 12 Bytes used: 192
5
.
.
.
.
.
Block length: 1014 Bytes used: 16224
507
Block length: 1016 Bytes used: 16256
508
Block length: 1018 Bytes used: 16288
509
Block length: 1020 Bytes used: 16320
510
Block length: 1022 Bytes used: 16352
************REBOL CRASHES HERE***********************
>> a: system/stats
== 3281456
>> make block! 100000
== []
>> b: system/stats
== 4882992
>> ( b - a ) / 100000
== 16.01536
>>
Second test-result:
.
.
.
Block length: 1266 Bytes used: 20256
633
Block length: 1268 Bytes used: 20288
634
Block length: 1270 Bytes used: 20320
635
Block length: 1272 Bytes used: 20352
636
Block length: 1274 Bytes used: 20384
637
Block length: 1276 Bytes used: 20416
638
Block length: 1278 Bytes used: 20448
************REBOL CRASHES HERE***********************
Think it would be of interest for all.
Thorsten
-----Ursprüngliche Nachricht-----
Von: [rebol-bounce--rebol--com] [mailto:[rebol-bounce--rebol--com]]Im Auftrag
von [Robbo1Mark--aol--com]
Gesendet: Donnerstag, 2. August 2001 14:53
An: [rebol-list--rebol--com]
Betreff: [REBOL] Memory Allocation & Self Modifying Code
Memory Allocation & Self Modifying Code
This mailing will discuss some predictive theories on
REBOL Block! memory allocation and also how it effects
the result of performing some self modifying code
expressions.
DISCLAIMER:
I only had REBOL/Core 2.5 running on Windows 95 available
whilst performing these tests / enquiries so I can only
make statements about results I found in relation to this
REBOL version and platform combination, I do not know how
this compares to other REBOL versions & platforms etc.
REBOL Block! Memory Allocation.
In relation to an earlier thread this week What Kind of Bug is
This? I was intrigued as to why a self modifying REBOL expression
always appeared to make errors at the same places but not at
others.
Ladislav Mecir mentioned that this was probably due to the REBOL
implementation issues and Brian Hawley reckoned it was most likely
due to the way memory is allocated for REBOL Block! values.
This guided my thinking & enquiries, and if you wish you can repeat
my tests with the following code.
>> Echo %test.txt
>> a: [ append a [+ 1] 1]
>> loop 1000 [ print [ do a newline ] print [ "Block length: " length? a
Bytes used:
((length? a) * 16) ] ]
I ran this code until REBOL crashed at the following stage
254
Block Length: 510 Bytes Used 8160
Careful examination of Test.txt file reveals the following positions where
REBOL makes errors.
Block Length: 14 Bytes Used 224
6
Block Length: 16 Bytes Used 256
8
.....
Block Length: 28 Bytes Used 448
14
Block Length: 30 Bytes Used 480
14
Block Length: 32 Bytes Used 512
16
.....
Block Length: 28 Bytes Used 448
14
Block Length: 30 Bytes Used 480
14
Block Length: 32 Bytes Used 512
16
.....
Block length: 60 Bytes used: 960
30
Block length: 62 Bytes used: 992
30
Block length: 64 Bytes used: 1024
32
.....
Block Length: 124 Bytes Used 1984
62
Block Length: 126 Bytes Used 2016
62
Block Length: 128 Bytes Used 2048
64
.....
Block Length: 252 Bytes Used 4032
126
Block Length: 254 Bytes Used 4064
126
Block Length: 256 Bytes Used 4096
128
.....
Block Length: 380 Bytes Used 6080
190
Block Length: 382 Bytes Used 6112
190
Block Length: 384 Bytes Used 6144
.....
254
Block Length: 510 Bytes Used 8160
###### REBOL CRASHES HERE ##########
Now it was earlier postulated on this list
that in BLOCK! values REBOL allocates approximately
16 bytes per value. ( Or to put it another way all
REBOL values / datatypes could be contained within
a 16 byte value with pointers used to areas of
memory storage for series! type values like block!
and string! data. )
REBOL Tech staff also pointed out that users shouldn't
speculate on such things because it can be highly platform
dependant and also subject to change, which is fair enough
and true, but specualting on inner secrets of REBOL is
interesting ( well to me anyway ; ) so I'll continue.
The following code would appear to validate the theory
of approximately 16 bytes per value for Block! types.
>> a: system/stats
== 1463472
>> make block! 100000
== []
>> b: system/stats
== 3065008
>> ( b - a ) / 100000
== 16.01536
>>
So assuming that each value is ~16 bytes we can return to
the results of Test.txt and we see an interesting pattern
emerging.
REBOL Block! it would seem automatically allocates sufficient memory
to hold 16 values or 256 bytes.
The first error occurs as the evaluted block encroaches on this limit
of 16 values. The next error occurs as the evaluated block encroaches
upon 32 values, so we can infer that REBOL allocated another 256 bytes
block space in addition to the original 256 bytes.
The next errors occur at encroaching 64 , 128, 256, 384 & 512 values.
>From this I deduce that REBOL Block!'s allocate memory thus...
STAGE 1. 256 bytes or 16 values initial allocation
STAGE 2. 256 bytes or 16 values additional allocation
STAGE 3. 512 bytes or 32 values additonal allocation
STAGE 4. 1024 bytes or 64 values additional allocation
STAGE 5. 2048 bytes or 128 values each additional allocation thereafter.
If we think in terms of THE LANGUAGE THAT MUST NOT BE MENTIONED and do our
own memory allocation in a new REBOL session we see that the self modifying
block expression runs correctly without any glitches at least until it
reaches
our set block! allocation limit.
Try this....
>> echo %test2.txt
>> a: make block! 1024
== []
>> insert a [append a [+ 1] 1]
== []
>> a
== [append a [+ 1] 1]
>> loop 1000 [ print [ do a newline ] print [ "Block length: " length? a
Bytes used:
((length? a) * 16) ] ]
Examining Test2.txt we see that REBOL happily & correctly evaluates away
until we get to my Block! set upper limit of 1024 values.
Block length: 1018 Bytes used: 16288
509
Block length: 1020 Bytes used: 16320
510
Block length: 1022 Bytes used: 16352
###### REBOL CRASHES HERE #############
So we can see that by utilising Memory Allocation techniques just as one
would in THE LANGUAGE WE DARE NOT MENTION IT'S NAME we can happily use
self modifying code in this manner.
Does anybody have any comments or obtain differeing results on their
appropriate REBOL version / platform combination, as I'm interested to
see how REBOL performs in those instances.
Feel free to comment here.
Cheers everybody,
Mark Dickson