DreamLight Interactive

DreamLight Director Talisman

DreamLight.com

Search/Index Help
Click to view DreamLight's 3D Animation Demo Reel
20+ Years of Award-winning Multimedia, 1987-2007

Managing Memory with Director’s Lingo
& DreamLight Director Talisman Tips & Tricks

DreamLight RAMLightPrevious Contents Next

Managing Memory sometimes seems like a black art. Memory leaks can lead to various problems such as Type 11 crashes on the Mac or GPF crashes under Windows. They can also create other bizarre behavior that is extremely difficult to debug. If you are encountering strange behavior while debugging a project, one of the first things I’d suggest examining, is what exactly is going on in RAM.

I have even created a neat little memory management utility called DreamLight RAMLight to help multimedia developers using Director, Shockwave or other web technologies get a handle on their memory management.

It’s really not as difficult as many believe to take a more active role in your multimedia’s memory management. Armed with the following tips from some of my previous posts to the Direct-L list, and DreamLight RAMLight, you should be able to keep from losing your memory before your time.

Warning: There are problems with the memory properties in Director on Windows, DreamLight RAMLight (or any other memory related Lingo) may not report actual memory use in Director on Windows since the freeBlock and the freeBytes Lingo properties may not function properly on Windows. These Lingo properties (and DreamLight RAMLight) will function properly in Director 7.0.2-8.5.1 on Macintosh. You can test if the freeBytes works on your Windows machine by putting the freeBytes in the watcher and opening some large files. the freeBytes should shrink appropriately, once available virtual memory begins to run low. If it does not, then the memory Lingo properties (and DreamLight RAMLight) may not work on your machine.

Enjoy,

Michael Scaramozzino

Michael Scaramozzino
President and Creative Director

DreamLight Director Talisman
Director Tips & Tricks

Authorized Macromedia Developer

Contents

Top

Bug Report:
Memory Properties on Director for Windows

Top

Date: Feb. 26, 2002

Description

The memory properties (and/or memory handling) do not function properly on Windows.

Expected Behavior

the freeBytes should shrink before Director runs out of memory. Even if it bounces around due to Windows' virtual memory implementation, it should finally begin to shrink if Director is finally exhausting all available memory.

Actual Behavior

the freeBytes remains extremely high, even though Director runs out of memory and forces a save/quit... This effectively renders "the freeBytes" useless under Windows. It appears (as you'll see below) that the freeBytes is reporting on unused virtual memory (as it should), but Director is not using that virtual memory for some reason and just quitting when physical RAM is used up...

(Please let me know if you can't reproduce the following on your system, I'm not sure if it's specific to certain Windows machines or across the board.)

Test Machine

CompUSA Celeron PC with 64MB RAM running Windows 98, Director 8.5.1

Steps to Reproduce

1) Create a new D8.5.1 movie with the following script on the Macintosh where Director is set to use system temporary memory, but virtual memory is OFF:

property spriteNum, MySprite, MyMember, aMegaByte

on beginSprite Me
  Me.MySprite = Sprite( Me.spriteNum )
  Me.MyMember = Me.MySprite.Member
  Me.aMegaByte = 1024 * 1024
  Me.updateMem()
end

on exitFrame Me
  member("Picture 1").duplicate() -- lets use up all memory...
  Me.updateMem()
  go to the frame
end

on updateMem Me
  put EMPTY into output
  put "the freeBytes:" && Me.transMem(the freeBytes) after output
  put RETURN & RETURN after output
  put "the freeBlock:" && Me.transMem(the freeBlock) after output
  put RETURN & RETURN after output
  put "the memorySize:" && Me.transMem(the memorySize) after output
  put output into Me.MyMember 
end

on transMem Me, bytes
  megaBytes = bytes / aMegaByte
  remainingBytes = bytes mod aMegaByte
  kiloBytes = remainingBytes / 1024
  remainingBytes = remainingBytes mod 1024
  return megabytes && "MB +" && kilobytes && "K +" && remainingBytes && "B"
end

2) Set the script to be a behavior.
3) Create a text field on the stage.
4) Attach the behavior to the text field.
5) Take a screen shot of the entire screen while set to millions.
6) Drag the screen shot into the cast.
7) Name the screen shot "Picture 1".
8) Save the movie now.
9) Open Director's memory inspector
10) Run the movie on the Mac

As expected: You'll see the freeBytes shrink by the size of the bitmapped cast member being duplicated (9.5MB on my dual monitor system). Director's memory inspector will also show free memory shrinking similarly. Once the temporary system memory is exhausted, the freeBlock will begin to shrink in tandem with the freeBytes. Then when the freeBlock gets down below 9.5MB, Director puts up the following dialog...

Warning! The current movie has used all of Director's main memory and most of it's reserve memory. Please save any changes immediately... (Quit) (Save As) (Save)

See Fig. 1

11) Hit Quit. (We don't want to save all the duplicated members.)
12) Copy the movie over to a Windows machine.
13) Open the movie in Director 8.5.1 under Windows.
14) Open Director's memory inspector.
15) Run the movie.

This is what happens here...

The freeBytes stays bouncing around at 65 MB (within a few hundred K but never drops below 65MB) even as Director runs out of memory, putting up the following alerts:

Out of memory, even after purging all purgeable castmembers. (OK)

Warning! The current movie has used all of Director's main memory. Please save any changes immediately... (Save As) (Save) (Exit)

See Fig. 2

The freeBlock and the memorySize both report 63MB + 312K +0B and never change. (This machine has 64MB of physical RAM). As you noted, it would be VERY nice to get the freeBlock working on Windows, it's currently not useful.

What's curious here is that according to the memory inspector, once the used memory crosses the physical memory, Director runs out of memory, without going into the unused virtual memory. This may be why the freeBytes are still high. There is a lot of free memory available in the virtual memory space, but as soon as the physical RAM is full, Director runs out of memory.

Now I thought, maybe the problem is that the cast must fit into the physical RAM, so instead of duplicating members, let's try using the new image objects to use up the memory in the program's portion rather than the cast, to see if it makes any difference. It didn't...

16) Replace the script behavior with this version:

property spriteNum, MySprite, MyMember, aMegaByte, images


on beginSprite Me
  Me.MySprite = Sprite( Me.spriteNum )
  Me.MyMember = Me.MySprite.Member
  Me.aMegaByte = 1024 * 1024
  Me.images = [ member("Picture 1").image.duplicate() ]
  Me.updateMem()
end

on exitFrame Me
  
  Me.images.add( Me.images[1]Duplicate() ) -- lets use up all memory...
  Me.updateMem()
  put RETURN & "Image count:" && Me.images.count after Me.MyMember
  
  go to the frame
end

on updateMem Me
  put EMPTY into output
  put "the freeBytes:" && Me.transMem(the freeBytes) after output
  put RETURN & RETURN after output
  put "the freeBlock:" && Me.transMem(the freeBlock) after output
  put RETURN & RETURN after output
  put "the memorySize:" && Me.transMem(the memorySize) after output
  put output into Me.MyMember 
end

on transMem Me, bytes
  megabytes = bytes / aMegaByte
  remainingBytes = bytes mod aMegaByte
  kilobytes = remainingBytes / 1024
  remainingBytes = remainingBytes mod 1024
  return megabytes && "MB +" && kilobytes && "K +" && remainingBytes && "B"
end

17) Run it again...

See Fig. 3

As you can see, we still run out of memory when the amount used by the program crosses the physical RAM boundary, but never get to use the free 65MB reported from the virtual memory partition...

Now, I'm not really sure where the problem is. It could be that the freeBytes is incorrect, but the more I investigate this it looks more and more like Director is not using the free memory that is available to it... Who knows?

Suggestions to improve Lingo's memory reporting functionality:

The memory inspector reports total memory which takes the virtual memory into account. Currently, the memorySize reports total memory on the Mac but it only reports the physical RAM under Windows. It would be much more useful and more consistent if the memorySize reported total memory on both systems, and if there were a new property that reported the physicalRAM on both systems.

If you don't want to break the current implementation of these properties, then what about adding a new set of memory properties to the environment property list?

These are what I'd love to see if at all possible, operating the same across both platforms:

the environment.memory.freeBytes = actual free bytes available accounting for all free memory available including virtual memory.

the environment.memory.freeBlock = actual free block available in the entire virtual memory partition.

the environment.memory.RAM = actual amount of physical RAM installed on the machine.

the environment.memory.total = total memory available, including virtual memory as reported by the memory inspector.

the environment.memory.used = total amount of memory that is currently being used by Director.

It looks like Director itself is calculating all of these values during authoring as shown it the memory inspector. Why not make these same values available through Lingo?

With such solid memory properties, it would be much easier for developers to keep a handle on the memory management of their projects.

-MikeS

Re: Memory Properties,
freeBytes/freeBlock works on some Windows PCs

Top

Date: Feb. 5, 2002

After my request for others to try and run the Lingo memory tests on Windows I had one report of the memory Lingo functioning properly on Windows 2000 Pro, and many responses saying that the freeBytes hasn't worked on Windows since D6. So, the problems appear to be more ephemeral than I had expected.

Here are some quotes from my conversation with someone who's freeBytes works on Windows in D7.0.2, D8 and D8.5:

>> Can some others out there try running this test on various versions
>> and updates of Windows, to see if this as an across the board problem
>> or not?

> Machine specs: Win 200 Pro w/ 256MB RAM & SP2 installed.

> Interestingly, if I create a bitmap in the paint window - while the movie is
> running - and hit CTRL-D to repeatedly duplicate it in the castLib, the
> freeBytes drops consistenly while the freeBlock doesn't budge, until the
> first MB change in the freeBytes, when both it and the freeBlock drop around
> 20 MB then both decrease in tandem. Consistent across all 3 versions. No
> idea *what* that means.

>> Are you saying that the freeBytes and the freeBlock actually started
>> to work properly once you had duplicated the cast members a certain
>> number of times?

>Yep. Exactly as described.

>> When I try that here on D8.5.1 in Windows 98, the freeBlock remains
>> pegged to the memorySize and the freeBytes seems to bounce around
>> slightly within a few hundred K, until finally Director puts up the
>> "used all available memory" alert and quits. Even as the alert comes
>> up, the freeBytes still says all the memory is free...

> For me, the freeBytes seems to work as it should - drops consistently from
> the first duplication and continues to do so. Only after a period of
> time/number of duplications does the freeBlock also start to drop. I didn't
> stick with it long enough to get the "used all available memory" alert.

Memory Properties,
Problems in Director on Windows

Top

Date: Jan. 30, 2002

There are a few problems with the memory properties in Director when running under Windows.

1) Attach the following script to a field sprite:

property spriteNum, MySprite, MyMember, aMegaByte

on beginSprite Me
  Me.MySprite = Sprite( Me.spriteNum )
  Me.MyMember = Me.MySprite.Member
  Me.aMegaByte = 1024 * 1024
end

on exitFrame Me
  put EMPTY into output
  put "the memorySize:" && Me.transMem(the memorySize) after output
  put RETURN & RETURN after output
  put "the freeBytes:" && Me.transMem(the freeBytes) after output
  put RETURN & RETURN after output
  put "the freeBlock:" && Me.transMem(the freeBlock) after output
  put output into Me.MyMember
  
  go to the frame
end

on transMem Me, bytes
  megabytes = bytes / aMegaByte
  remainingBytes = bytes mod aMegaByte
  kilobytes = remainingBytes / 1024
  remainingBytes = remainingBytes mod 1024
  return megabytes && "MB +" && kilobytes && "K +" && remainingBytes && "B"
end

2) Run the movie and you should see something like this in the field:

the memorySize: 368 MB + 0 K + 0 B

the freeBytes: 169 MB + 440 K + 886 B

the freeBlock: 48 MB + 130 K + 288 B

3) Then, while the movie is still running, open "About Director"
(Apple Menu on Mac, Help Menu on Windows)

You should see the freeBytes drop by about 5 Megabytes
If you do not, then the freeBytes property may not be working properly.

You can also open the memory inspector, create a bitmap cast member, run the movie, and keep duplicating the cast member in the cast. This should start to use up memory which you'll see in the memory inspector. The freeBytes should shrink accordingly.

Here are the results of some quick tests:
Director 7.0.2, MacOS 9.0.4: Works fine
Director 8.5.1, MacOS 9.0.4: Works fine
Director 7.0.2, Windows 98: Does not work (but I thought it did before...)
Director 8.5.1, Windows 98: Does not work

In Director 8.5.1 (& 7.0.2) on Windows 98, this is what I get:
the memorySize returns close to the physical ram in the machine
the freeBytes returns about 2 MB more than the memorySize
the freeBlock simply returns the memorySize

I could have sworn I had tested this a while ago in D7.0.2 on the same Windows 98 machine and it worked. I installed Director 8.5.1 on the same machine, does this update any libraries that D7.0.2 may also use, which could explain why that no longer works? We may have performed a couple of Windows Service Pack Updates on the machine in the mean time as well. Does anyone know of any updates that interfere with Director's memory reporting?

Can some others out there try running this test on various versions and updates of Windows, to see if this as an across the board problem or not?

Thanks,
-Mikes

Bug Report: (more)
preloadMember & unloadMember

Top

Updated: Feb. 14, 2002
Original post date: Jul. 18, 2000

Description:

preloadMember and unloadMember without any arguments are used to load or unload all cast members in a movie. As I noted before, they generate script errors if for any reason castLib 1 is empty (Script errors are fixed in D8.5.1). If any castLib other than castLib 1 is empty, they don't generate script errors but preloadMember only loads members up to the empty cast and then it stops, it won't affect any members in castLibs beyond the empty one. unloadMember however will work across an empty castLib. This bug was first reported in D7.0.2 and it still exists in D8.5.1.

Steps to reproduce:

1) Create a new movie with three internal castLibs.

2) Put a bitmap member in member 1 in castLib 1, castLib 2 and castLib 3.

3) Save the movie.

4) Open the message window and type the following.

preloadMember
put (member 1 of castLib 1 ).loaded
-- 1


put (member 1 of castLib 2 ).loaded
-- 1


put (member 1 of castLib 3 ).loaded
-- 1 

5) All members are loaded as expected, now type this...

unloadMember 
put (member 1 of castLib 1 ).loaded 
-- 0 


put (member 1 of castLib 2 ).loaded 
-- 0 


put (member 1 of castLib 3 ).loaded 
-- 0 

6) All members are unloaded as expected.

7) Now delete member 1 of castLib 2 leaving castLib 2 empty.

8) Save the movie again.

9) Type the following in the message window.

preloadMember 
put (member 1 of castLib 1 ).loaded 
-- 1 


put (member 1 of castLib 3 ).loaded 
-- 0 

10) Note that since castLib 2 is empty, the preloadMember stopped there and no members of castLib 3 were loaded.

11) Now try this...

preloadMember( member 1 of castLib 3 ) 
put (member 1 of castLib 3 ).loaded          
-- 1 


unloadMember 
put (member 1 of castLib 3 ).loaded 

-- 0 

12) unloadMember does work across an empty castLib (as long as the empty castLib is not castLib 1 which will generate an error instead) but preloadMember does not.

Personally this is how I would expect these commands to work:

preloadMember without arguments should simply load any and all cast members that a movie may have. If the movie or any castLibs are empty that should not affect this command at all. If there are any cast members in any castLibs they should be loaded by this command. Empty castLibs should simply be ignored rather than interrupting the command. If there are no members in any castLib then preloadMember should do nothing.

-MikeS

Bug Report:
preloadMember & unloadMember

Top

Date: Jul. 18, 2000

Description:

preloadMember and unloadMember without any arguments are used to load or unload all cast members in a movie. However, they generate script errors if for any reason castLib 1 is empty. Normally castLib 1 would not be empty but if you are dealing with multiple dynamically loaded casts there could be an instance where castLib 1 is currently empty, in which case preloadMember and unloadMember without arguments both fail, even if other castLibs have members.

Steps to reproduce:

1) Create a new movie with two internal castLibs.

2) Put a bitmap member in member 1 in both castLib 1 and castLib 2.

3) Save the movie.

4) Open the message window and type the following.

preloadMember 
put (member 1 of castLib 2 ).loaded 
-- 1

5) The member is loaded as expected, now type this...

unloadMember 
put (member 1 of castLib 2 ).loaded 
-- 0 

6) The member is loaded and unloaded as expected since preloadMember and unloadMember without arguments load and unload all members.

7) Now delete member 1 of castLib 1 leaving castLib 1 empty.

8) Save the movie again.

9) Type the following in the message window.

preloadMember 

10) Script error. Cast member name expected. preloadMember

unloadMember 

11) Script error. Cast member name expected. unloadMember

I don't think preloadMember or unloadMember should generate errors if castLib 1 is empty. I tested this on MacOS 9.0.4 under D7.0.2. Someone may want to test it under D8 to see if this has been fixed. [Update 8/24/00: Early indications are that it still exists in D8 and probably went back long before D7 as well]

-MikeS

Lingo to Report a Frame’s RAM Usage

Top

Date: Aug. 1, 1997

>I'm aware that there are extras out there that can do this but is there
>a "lingo" way to determine the amount of memory you are using on a given
>frame? I'd like to determine if I'm loading too many graphics, audio,
>etc. at one time.

Take a look at the DreamLight RAMLight. It's a little utility built entirely in Lingo.

<http://www.dreamlight.com/webshop/utilities/ramlight.html>

The RAMLight Object uses the following lingo handler from a MIAW to report on frames in the main movie.

on reportFrames me, start, stop
  if start = 0 AND stop = 0 then
    tell the stage to put the lastFrame into stop
  end if
  
  tell the stage to put the frame into savedFrame
  
  if  start <= 0 then set start to 1
  if stop < start then set stop to start
  
  put "--------------------------------------"
  put "DreamLight(R) RAMLight(TM)"
  put "FRAME REPORT" && "Range:" && start && "-" && stop
  put "--------------------------------------"
  repeat with i = start to stop
    tell the stage
      go to frame i
      put ""
      put "FRAME #:" & i
      repeat with j = 1 to 48
        set k to the castNum of sprite j
        if k > 0 then
          put k & ":" & the name of cast k && "|" && ¬
                  the castType of cast k && 
                  "| PP:" & the purgePriority of cast k && "|" && ¬
                  the size of cast k/1024.0 & "K"
        end if
      end repeat
    end tell
  end repeat
  put "--------------------------------------"
  tell the stage to put "RAMNeeded:" & ramNeeded( start, stop )/1024 & "K"
  put "--------------------------------------"
  
  tell the stage to go to savedFrame
end

Please note that this only reports on cast members that appear in the score, not castmembers loaded from Lingo. You can still test Lingo loaded castmembers by using the RAMLight's thermometer readout which reports on everything as the movie plays.

-MikeS

Disk Thrashing Slowdown on Windows

Top

Date: Jul. 15, 1997

>Nope. I've traced the code quite well. The mystery is further compounded by
>the fact that NO CODE CHANGED between the "slow" version and the "fast"
>version... only a couple of graphics were edited. I'm totally baffled here.
>The only thing I can think of is that I've overloaded some internal buffer,
>sorta like the old days when a script exceeded 30,000 characters...

I just jumped in here so I'm not sure what the original question was. I noticed you talking of a slow version and fast version. This reminded me of a problem we once encountered. It may not be applicable but just in case let me outline what happened.

On the Windows version of a hybrid CD-ROM we were developing, we were occasionally getting very bizarre behavior. The Mac version was fine.

Periodically the Windows version would go into super slow motion. The project is called KeyQuest, A typing adventure. Sometimes while typing it would slow to a rate of about one keystroke per second.

Upon lots of detective work we traced the problem down to a memory issue brought on by a combination of two factors.

First off, we found a bug in the D4/D5 Windows version of the puppetSound where sounds were forever locked in memory (this has been posted, so I won't repeat here). This then led to a low memory situation which became exacerbated by a large background image we were using behind many foreground sprites during the lessons.

What would happen is that when memory got low, the movie would load all cast members for the frame. Then when the user typed a letter it must have purged the background because it would then immediately reload the background. So we would get stuck in a disk thrashing loop where between every keystroke Director would reload the large background.

The solution was handled three ways.

  1. On Windows, we issued a puppetSound sndChnl, 0 before playing any new sound.

  2. We implemented a memory checking handler that preloads each frame before we need it. This enabled us to gracefully abort if we ran out of memory.

  3. We merged the large background to each of the foreground elements so we could display one large cast member rather than a large background with additional items floating on top of this large background. This was a less efficient use of the cast members but more efficient for Director to play.

This solved our Windows memory/disk thrashing problem.

-MikeS

Quick Shockwave RAM Test

Top

Date: Jul. 11, 1997

You can run a quick RAM test (immediately) on your Shockwave page to watch exactly what is eating up all your RAM. This will test ALL content on the page including images, Shockwave, JAVA or anything else there.

Simply follow these simple steps.

  1. Point Netscape at the following on-line URL: http://www.dreamlight.com/webshop/utilities/ramlight.html After this page loads it will open a little floating window called the DreamLight RAMLight.
  2. Close the main browser window, but leave the small floating RAMLight open.
  3. Open a new browser window
  4. Point the new browser window to your web page (on-line or local, doesn't matter)
  5. Watch the DreamLight RAMLight as your page loads and runs. It reports on the entire web browser partition including all content. You can see exactly when the memory use jumps.

Hope it helps! -MikeS

PS. For a little fun, leave the RAMLight open and go surfing around the Internet to see how much RAM anyone's pages eat...

Windows puppetSound Memory Leak

Top

Date: Jul. 9, 1997

>I've tried that but it doesn't make any difference.  I'm using a combination
>of score sounds and puppetsounds and they both seem to have the same effect.
>If I watch the memory inspector the memory gets taken up in the Cast & Score
>section but only gets released if I click on the Purge button, which I can't
>get to via lingo.

--

>I've witnessed this behavior before also. In one project I had some
>looped background sound files (300k) which switched every minute or
>two.  Sure enough, every time it switched the memory inspector jumped by
>300k.  We could NOT find a way to purge the memory from lingo.  (I even
>made a handler which stepped through all the cast members and unloaded
>everything!)
>
>I suspect (for no good reason) that it has something to do with
>contiguous free bytes.  (Mearly a theory on my part...)
>
>In my case, the leak was very slow and would cause the projector to
>freeze after running for 3 or 4 hours.
>

There is a [SDF] in the puppetSound in D4/D5/Win where sounds that are puppeted are NEVER released unless you actually issue a puppetSound channel, 0 to break the link to the sound before puppeting another sound into the channel. If you acidently puppet another sound into the same channel before clearing it out with the puppetSound channel, 0 first, then the first sound is forever locked in RAM... until the projector quits!

This only happens under Windows, D4/D5/Mac would release the sounds as expected and the puppetsound channel, 0 was not necessary.

I wrote the DreamLight RAMLight while tracking down this very [SDF] which was crashing the windows versions of a hybrid CD-ROM we finished a while ago. Full details should be in the archives.

>Unfortunatly, I found it after the fact. Therefore, to avoid tracking
>down each puppetSound instance only to add a puppetSound chnlNum, 0, why
>couldn't I add a handler in my movie (or linked cast) like:
>
>        on puppetSound chnl, name
>                puppetSound chnl, 0
>                puppetSound chnl, name
>        end puppetSound
>
>I've tested it and it seems to work, but I'm looking for any feedback.
>Am I overlooking something? It seems to easy a solution.

That is close to the solution we used last year. We had our sound manager object create channel objects that controled each sound channel. This enabled us to do fancy cross fades and other neat things with the audio. When we wanted to play a sound we would pass it to the channel manager instance of a particular sound chanel. Before that channel manager puppeted the sound however, it would test if it were running under Windows and if so it would puppetSound channel, 0.

OOPS!!!

Upon a little closer examination I noticed that you used the keyword "puppetSound" for your own handler name. That's a no-no... That probably won't work the way you expect. You need to make up your own handler name.

>
>        on puppetSound chnl, name
>                puppetSound chnl, 0
>                puppetSound chnl, name
>        end puppetSound
>

Something like this would be better...

on pcSafePuppetSound chnl, name
   puppetSound chnl, 0
   puppetSound chnl, name
end pcSafePuppetSound

---

Below are a few code fragments that we used in our SoundManager/SoundChannel objects when we isolated the [SDF]...

on doPuppetSound me, whichSound
  global gTheMovieMan, gTestMode, gMac
  
  set whichCast to the number of cast whichSound
  if whichCast > 0 then
    loadCast( gTheMovieMan, whichCast )
    if NOT gMac then puppetsound( mySoundChannel, 0 )
	-- break link to prior cast for PC...
    puppetSound( mySoundChannel, whichCast )
  else
    if gTestMode then
       Alert ¬
       "SoundChannel/doPuppetSound:Can not find sound castmember:" && whichSound
    end if                         
  end if
end doPuppetSound

--

doPuppetSound (all one word) is one of the methods of our SoundChannel object. We instance one of these manager objects for each channel we intend to use... It performs many other fuctions such as cross fades, playing lists of sounds etc...

loadCast is a method of the MovieManager object which performs a memory test to see if the intended castmember will fit in RAM. It purges memory if necessary until the sound fits into RAM. If it fails it aborts the movie with a graceful "out of memory" alert rather than letting the projector crash...

We then test for gMac which is a global variable we set to TRUE if we are running on a Mac. If it's not a Mac we then issue the magical puppetSound( mySoundChannel, 0 )

mySoundChannel is the property variable which holds the number of the sound channel for this particular SoundChannel object.

If we are running in gTestMode (a global used during debugging) we output that a requested sound is missing. In the final project gTestMode is set to false.

Hope this info helps...

-MikeS

PS Some of the parenthesis are not necessary but I use them to make the code easier to read...

Using the freeBytes to Check RAM

Top

Date: Jul. 9, 1997

>Isn't the fact that you are putting the freebytes to the window that the
>window takes up bytes to store the display of the freebytes... get it

Yes, it's kind of like the uncertainty principle... Observing the FreeBytes that way changes them... ;-)

You can't create a simple loop that repeatedly issues a:

put the freeBytes

because the text number that gets added to the message window each time takes up space itself. So it will look like you have a memory leak where each successive number in the message window will be smaller than the last... Eventually you'll run out of RAM.

Check out the DreamLight RAMLight for a more reliable test of memory leaks...

-MikeS

What’s Hanging Around in RAM?

Top

Date: Jul. 7, 1997

>I got curious and wondered what was hanging around in memory so I ran
>through all the members checking the 'loaded' property and found that
>*all* of my fields and a lot of my bitmaps were returning TRUE. I read in
>the manual that #shape and #script cast members are always loaded....
>does this apply for fields too? And why are some of my bitmaps still in
>memory? This even occured after an unloadmember command.

The DreamLight RAMLight can give you full reports on what's hanging around in memory and what has been successfully purged. It may help you isolate what's causing your cast members to stay in memory.

This enabled us to find the Director 4/5 bug about puppetsounds not being released under Windows the way they were under the Mac. (I hope that's fixed in Director 6, I haven't tested it yet... but will very shortly ;-)

-MikeS

Type 11 and GPF Crashes in MIAW

Top

Date: Mar. 25, 1997

>This is really neat, except that when I test it, I can open and close it
>between 1 and 20 times before getting a Type 11 error (Mac).  Most of the
>time, the error comes during the opening process, just before the window
>opens.  Sometimes, the error comes as the window closes.

I'm only guessing here but there a couple of things I would test first.

1) Are you using the actorlist or some other such method of incremental processing? If you are killing objects that are in the current call chain you can get a Type 11 crash when control tries to return to an object that no longer exists. You can also get a Type 11 if deleting objects from the actorlist during a stepframe in a similar situation.

2) Is your MIAW loading large cast members into RAM? You could be running out of memory which can also cause a Type 11 crash. You can leave the memory inspector open as the project runs and watch the free memory. To examine your memory use even more accurately you can try the DreamLight RAMLight...

You can also use the DreamLight RAMLight as an example of programming a MIAW using object oriented programming. It includes the full Lingo source code as an example. (you may learn from the code, pleased don't copy the code itself though.)

Hope this helps...

-MikeS

Testing Shockwave, QuickTime, QTVR RAM Use

Top

Date: Feb. 4, 1997

>Rasmus Keldorff writes on Jan 31 of seeing a -108 memory alert in Netscape
>Navigator 3.0/Mac on pages which contain four Shockwave instances and which also
>have QuickTime and QTVR content.

Having memory problems with Shockwave, or anything on the Web for that matter?

Check out the DreamLight RAMLight. It can help you track memory use by your browser whether it's using shockwave, QT, QTVR, or anything else for that matter. It reports on your browser's entire memory partition reflecting impact from all currently open pages with their entire contents...

It should help you track down any memory issues.

-MikeS

Disposing of Objects in RAM

Top

Date: Jan. 14, 1997

>Does anybody knows whether the memory occupied
>by a big object is freed by simply using the command
>"set oVariable = 0" or there's any other similar way to do it?

Simply break all references to the object and it will be deleted. This means resetting ALL variables that are pointing to it (including any references in the actorlist etc.), to 0. That will do the trick.

>My favorite, because it requires no extra code away from the point of use:
>
>   set gMyGroovyObject = value(void)

Actually I'm curious. Is this any better than simply setting it to 0, or is this more of a personal preference issue?

set gMyGroovyObject = 0

Neither method requires any code away from the point of use, and Director's loose typing easily allows putting the integer 0 into what used to hold an object pointer. Both methods result in releasing the object.

> set gMyGroovyObject = value(void)

The main benefit that I could see with the value(void) approach is that it may be a touch more obvious that you are clearing out a pointer. Does this approach actually release more memory? The memory used for the variable itself? Does setting it to void release it from the symbol table or something similar?

> set gMyGroovyObject = 0

The 0 approach that I usually use in Director is more concise but could be a touch more confusing if someone was reading another's code and didn't quite understand the reason for setting it to 0. This obviously will hold the integer 0 in memory where it is really no longer needed. If the vaule(void) approach actually removes the variable as well from memory, then I'd switch to using that method unless the variable is used again later and reset to point to an object again which would remove and then recreate the variable.

This brings up some subtle questions that I hadn't really considered before. I really didn't worry too much about such issues since Lingo is not strictly typed unlike C++.

When a variable of a certain type such as an object pointer is created in Lingo it obviously must reserve enough memory to hold such a pointer. Does subsequently putting an integer or other type of value into the variable type cast the value to the type of the original variable? Or, does it create a new variable of the new type (using a different amount of memory based on the new type)? And does setting it to value(void) actually destroy the variable itself releasing the variables memory (I'm not talking about the objects memory, but the memory used by the pointer itself) or simply set it to some type of null pointer value that does use memory until it goes out of scope?

Any technical details about how Lingo handles internal variables would be useful when considering such issues.

Are there any other subtle reasons for leaning one way or the other that I haven't considered?

-MikeS

>The continuing saga of nulling out an object reference...
>
>On 1/17/97, julian baker wrote (in part):
>> what's wrong with
>>   set gMyGroovyObject = void
>
>Unless you have a variable named "void" (and I hope you don't), this won't
>work inside a script. Lingo doesn't know "void", so it assumes it's the
>name of a local variable. When I try this line inside a script, I get
>"variable used before assigned a value".
>
>Incidentally, it *will* work in the message window, where unknown
>identifiers are assumed to be global variables initialized to void. (For
>the same reason, set gMyGroovyObject = FunkyGroovyLingoHacker will probably
>work just as well in the message window.)
>
>(VOID is one of those constants we keep meaning to add to Lingo. It'll
>probably show up in a future release.)
>
>
>On 1/15/97, Michael Scaramozzino wrote (in part):
>> >   set gMyGroovyObject = value(void)
>> Is this any better than simply setting it to 0
>
>Not particularly. As W. Dana Nuon pointed out, 0 won't work if you're using
>voidP to find uninitialized objects. Also, the showGlobals command
>suppresses display of globals whose value is void. It's really just a
>personal preference, though.
>
>
>Michael Scaramozzino also asks for...
>> Any technical details about how Lingo handles internal variables
>
>Here goes...
>
>> Does this [the value(void)]
>> approach actually release more memory? The memory used for the variable
>> itself? Does setting it to void release it from the symbol table or
>> something similar?
>
>Nope. The integer 0 and the value void both take up the same amount of memory.
>
>The amount of memory a value uses depends on the type of the value:
>
>- Simple types (integer, void, symbol) all take up the same, fixed amount
>of memory (currently 8 bytes, the same as a MoaMmValue).
>
>- Complex types (string, list, object, etc.) take up the same fixed memory
>as the simple types, plus additional memory to hold the variable length
>data.
>
>Lingo values always carry their types around with them. When a value is
>assigned into a variable, its type is assigned along with it. The type of
>value previously in the variable has no effect on the new type of the
>variable. (There's no automatic casting or anything like that.) If the
>previous value was a complex type, the additional memory it was using is
>released when all the references to it are gone.
>
>While a variable is alive, there's always a slot allocated to store its
>value. That slot is exactly the size needed for a simple value. One
>implication of this is that there is nothing you can assign into a variable
>to free the memory used by its slot, because even the void value takes up
>the standard slot size.
>
>There are three possible variable lifetimes in Lingo:
>
>- Local variables (those used only in a particular handler) are in scope
>only while the handler they are in is executing. Their slots are freed when
>the handler returns.
>
>- Properties are stored along with their object instances. There slots are
>freed when the object is destroyed (which is when all references to it are
>gone).
>
>- Global variables live forever (or at least, until you quit Director).
>clearGlobals will void out the values, but the slots themselves are not
>freed.
>
>Remember that a variable slot is just eight bytes. Even a whole movie's
>worth of global *slots* is unlikely to come anywhere near the memory used
>by the movie's bitmaps. Trying to optimize by freeing up slots is unlikely
>to have a big payoff. Complex values can take up a lot of memory, though,
>so it's reasonable to optimize by voiding out global references to large
>strings or lists when you're done with them.
>
>Hope this helps.
>
>- Mike Edmunds
>  Macromedia Director Engineering

Excellent information. The previous discussion had raised a couple of questions and you covered them all in sufficient detail.

Thanks,
-MikeS

Do Birthing Scripts Eat RAM?

Top

Date: Sep. 26, 1996

> 1. Does an instance of a 20K script take up 20K of RAM. Do 40 instances of
> that 20K script take up 800K of RAM.
>
> 400 instances - 8,000K ?        And so on.

No, there would only be 40 references to the script but not 40 copies of the script. Any property variables that the objects use and any cast members that they load would affect RAM, but not extra copies of the script.

> 2. If you can birth an object can you kill it also? I birth 800K worth of
> objects and then I want to flush them from RAM, how do I do this?

Just set all variables that point to the object to 0... This will free the objects memory (but not necessarily any castmembers that the object loaded).

You can watch the exact impact that objects have on your RAM with the DreamLight RAMLight...check it out... ;-)

-MikeS

Objects and Memory

Top

Date: Sep. 13, 1996

>Can anyone fill me in on how director allocates memory to objects. Especially,
>how does director deal with the space requires for the script and properties.

Memory impact that objects have should be quite minimal. The only memory that objects use are for their property variables. So, unless your object is creating a memory leak (through loading unintended cast members into memory or creating massive lists, etc.) they shouldn't consume much RAM at all.

>So John Dowdell is absolutely right. Each object has only a copy of the
>properties, not the handlers. (But the documentation is not accurate,
>because it is written that the child object has also a copy of the
>*handlers*, which is wrong)

Yes, it is a common misconception that the scripts are duplicated with the objects. The script is not really copied with each object but rather only referenced by each object. It acts as if it were copied but in reality it is only referenced. Thus the following statement is in error.

> Every object has its own separate script in memory. If ten objects are
>birthed from the same parent script there will be ten copies of the parent
>script around - one for each of the objects.

Upon careful examination, the example given below does not really support this statement above as intended, I'm sorry Peter Small, the logic is false. ;-). They are talking about two entirely different things. The example below is not really birthing ten objects from the same parent script as the statement suggests. It is birthing ten objects from different parent scripts that just happen to be located in the same cast member but at different times.

Since the script changes, these are all effectively different parent scripts and therefore the children will indeed each reference a different compiled script in memory. This is no different than birthing ten objects, one from each of ten different scripts located in ten different cast members.

>on mouseUp
>  global objects
>  set objects to []
>  put "" into field "girlie"
>  repeat with i =3D 1 to 10
>    put field "pScript" into workShop
>    put i into char (the number of chars in line 9 =A8
>    of workShop) of line 9 of workShop
>    set the scriptText of cast "pScript" to workShop
>    append objects,birth(script "pScript",i)
>    repeat with j in objects
>      mult j
>    end repeat
>  end repeat
>  put return & objects after field "girlie"
>end

If they were however all birthed from the same original unchanged parent script, then they would all be refering to the same compiled script in memory rather than to ten copies of the same script as the statement suggests.

This is my understanding of how Lingo works and I see this as a major benefit.

Otherwise birthing zillions of objects from a single parent wouldn't make much sense if each object actually had to copy the entire script each time. They all just REFER to the same compiled script in memory which is much more "practical".

;-)

-MikeS

PS. You can use the DreamLight RAMLight to examine the exact impact of birthing many objects from a single parent script.

Projector Memory Test

Top

Date: Jul. 24, 1996

>Are there any external apps(mac) that
>watch or record memory usage.  it would be great if I could just make my
>Projector's memory allocation HUGE, then launch a little app, then run
>my projector and have it record how much memory was really used.

Bingo!

If you include this code in your projector movie, you can open the DreamLight RAMLight right in your projector's memory partition.

on keyDown
   global gTestMode 
   -- set this to true in the startmovie handler during your test and 
   -- development phase.

   if gTestMode then
      if (the commandDown OR the controlDown) AND the key = "R" then
        open window "RAMLight"
      end if
   end if

end keyDown

Not only can you do this in a projector. The DreamLight RAMLight can dump memory use reports to the message window during development.

You can even use the DreamLight RAMLight to examine Netscape's entire memory partition under Shockwave.

BlastOff! The Award-winning 3D Animated Short film by Michael Scaramozzino - Special Edition DVD

Please Support Our Continuing Independent Film Making Efforts!
Order your Award-winning BlastOff! Special Edition DVD today!

BlastOff!™ Merchandise Available @ Telebites.com BlastOff! T-Shirts BlastOff! Hats BlastOff! Mugs BlastOff! Calendar, Prints & Posters BlastOff! Mousepads

Silver Sage Scrolls™ inspiration through the ages Available @ Telebites.com

To view this site properly, please upgrade to a browser that supports current Web standards.

 

BlastOff! Wins a Silver W3 Award in the Pioneering Category of Web Video - 3D Animation

BlastOff! Wins an Official Honoree Webby Award in the category of 3D Animation

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

DreamLight Incorporated, 323 Andover Street, Suite 6, Wilmington, MA 01887 USA, Telephone: 978-658-5110
Search/Index Top Help