Memory Management
Part 1 Objectives
- Define reference types
- Partially review, but hopefully this gives you a deeper understanding of why reference types behave the way they do.
- Describe a pointer
- Draw a memory diagram
Registers and Memory
Computers have two ways to store data. Registers and Memory.
variables, objects, and everything in a computer program is an abstraction around these mechanisms.
Registers
- Registers are very small - each one can store 64 bits
- Registers exist on the processor chip
- Data must be loaded into registers before the processor can use it
Memory
- All non-register storage can be considered memory
- L1-L4 caches, RAM, and hard-disc space are ALL in memory
L1 cache
L2 cache
L3 cache
RAM
Hard Disk
The Processor and the Registers
Memory
"Memory"
Although there are some limitations to this mindset, for now we are going to treat *all* of memory as one big bucket
Memory & Programs
Throughout the life-cycle of a program, data moves between memory and registers.
"Memory"
Memory & Programs
Because registers have limited storage, data that exceeds the limit must live in memory.
In JavaScript each integer is 64 bits. This array is therefore (at least) 5 times to large for a register.
var x = [1, 2, 3, 4, 5];
Memory & Programs
So our register gets a pointer to a memory address
var x = [1, 2, 3, 4, 5];
x = 0xFF019A
0xFF019A:
0: 1
1: 2
2: 3
3: 4
4: 5
Memory & Programs
x = 0xFF019A
0xFF019A:
0: 1
1: 2
2: 3
3: 4
4: 5
Hold up: Whats this?
Memory & Programs
This pointer is why Objects are called reference types. Our variable really holds a 64-bit pointer to a memory address
var x = [1, 2, 3, 4, 5];
x = 0xFF019A
0xFF019A:
0: 1
1: 2
2: 3
3: 4
4: 5
Memory & Programs
If we make a new variable and set it equal to x, this variable references the same memory location.
var x = [1, 2, 3, 4, 5];
var y = x;
x = 0xFF019A
0xFF019A:
0: 1
1: 2
2: 3
3: 4
4: 5
y = 0xFF019A
Memory & Programs
If we change one of the properties at that location both variables reflect the change.
x[0] = 100;
console.log(y[0]); // Prints 100
x = 0xFF019A
0xFF019A:
0: 100
1: 2
2: 3
3: 4
4: 5
y = 0xFF019A
Memory & Programs
But if we change what one of the variables points to then the modified variable points somewhere new.
y = [7,8,9]
console.log(y[0]); // Prints 7
console.log(x[0]); // Still prints 100
x = 0xFF019A
0xFF019A:
0: 100
1: 2
2: 3
3: 4
4: 5
y = 0xFF0EEE
0xFF0EEE:
0: 7
1: 8
2: 9
Lets Examine
http://pythontutor.com
Memory & Programs
If all our registers are filled, even 64 bit primitive types may have to be stored into memory and fetched again when they are needed.
There is *a lot* of hardware and software that we rely on to handle this for us, and our mental model doesn't need to be perfect.
(and probably couldn't be without years of study in Computer Engineering, Computer Science, and Operating Systems)
Memory Diagrams
Lets go here https://github.com/gSchool/computer-science-curriculum/blob/master/Unit-0/02-memory-diagrams.md
And look at some "memory diagrams" before we create some ourselves.
Stop when you get to "Prototypes" -- we'll discuss those later.
Take 10 minutes right now to read this
Now, Practice
Grab a mini-whiteboard and a partner
Objectives Review
- Define reference types
- Describe a pointer
- Draw a memory diagram
g35 Specific Slide
You all asked about Symbols, the new ES2016 (aka JavaScript 6) primitive type.
Now we have enough information to better understand Symbols.
var fooOne = new Symbol('foo');
var fooTwo = new Symbol('foo');
'foo' === 'foo' // this evaluates to true
fooOne === fooTwo; // What do you think this evaluates to?
// Why?
Objectives Part 2
- Describe "The Stack" and what data lives there
- Describe "The Heap" and what data lives there
- Describe "Garbage Collection" at a high level
- Stretch goal - appreciate how many countless hours of frustration John McCarthy has saved us all by inventing Garbage Collection.
Memory Groups
- Computer programs use two groupings for memory
- The distinction between these is 100% software - both use the same memory hardware
- They are called "The Stack" and "The Heap"
The Stack
- The Stack is for localized program memory
- Every time a function is called, space is allocated on the stack
- This "Stack Frame" contains local variables and pointers to function calls as well as "return addresses"
- Once a frame "pops off the stack" it is immediately freed as memory space.
The Stack
Learn by example
function fun1() {
var a = 1;
var b = 2;
return fun2(a, b);
}
function fun2(x, y) {
var c = x + y;
return c;
}
fun1();
We have the code to the left. Two functions are defined, then we call fun1.
The Stack
At the "top level" we're on whats called the global frame. Before anything happens, it's empty.
// YOU ARE HERE
function fun1() {
var a = 1;
var b = 2;
return fun2(a, b);
}
function fun2(x, y) {
var c = x + y;
return c;
}
fun1();
Global Frame: returnTo: null |
Every stack frame knows where it was called from. The global stack frame is special in that it isn't called from anywhere.
The Stack
After we execute the two function definitions, our stack looks like this
function fun1() {
var a = 1;
var b = 2;
return fun2(a, b);
}
function fun2(x, y) {
var c = x + y;
return c;
}
// YOU ARE HERE
fun1();
Global Frame: fun1: pointer to memory address fun2: pointer to memory address returnTo: null |
The Stack
Calling fun1 adds a new frame
function fun1() {
// YOU ARE HERE
var a = 1;
var b = 2;
return fun2(a, b);
}
function fun2(x, y) {
var c = x + y;
return c;
}
fun1();
fun1 Frame: returnTo: Global Frame |
Global Frame: fun1: pointer to memory address fun2: pointer to memory address returnTo: null |
The Stack
Local variables go onto the frame line by line
function fun1() {
var a = 1;
var b = 2;
// YOU ARE HERE
return fun2(a, b);
}
function fun2(x, y) {
var c = x + y;
return c;
}
fun1();
fun1 Frame: a: 1, b: 2 returnTo: Global Frame |
Global Frame: fun1: pointer to memory address fun2: pointer to memory address returnTo: null |
The Stack
Calling fun2 adds a new frame, parameters are already on the stack when they are passed in.
function fun1() {
var a = 1;
var b = 2;
return fun2(a, b);
}
function fun2(x, y) {
// YOU ARE HERE
var c = x + y;
return c;
}
fun1();
fun2 Frame: x: 1, y:2 returnTo: fun1 frame |
fun1 Frame: a: 1, b: 2 returnTo: Global Frame |
Global Frame: fun1: pointer to memory address fun2: pointer to memory address returnTo: null |
The Stack
c gets added after x+y is computed
function fun1() {
var a = 1;
var b = 2;
return fun2(a, b);
}
function fun2(x, y) {
var c = x + y;
// YOU ARE HERE
return c;
}
fun1();
fun2 Frame: c: 3, x: 1, y:2 returnTo: fun1 frame |
fun1 Frame: a: 1, b: 2 returnTo: Global Frame |
Global Frame: fun1: pointer to memory address fun2: pointer to memory address returnTo: null |
The Stack
Return pops the top stack frame off the stack and sends execution back to the caller
function fun1() {
var a = 1;
var b = 2;
return fun2(a, b);
// YOU ARE ABOVE
}
function fun2(x, y) {
var c = x + y;
return c;
}
fun1();
fun1 Frame: a: 1, b: 2, tmpVal: 3 returnTo: Global Frame |
Global Frame: fun1: pointer to memory address fun2: pointer to memory address returnTo: null |
The Stack
Return pops the top stack frame off the stack and sends execution back to the caller
function fun1() {
var a = 1;
var b = 2;
return fun2(a, b);
}
function fun2(x, y) {
var c = x + y;
debugger;
return c;
}
fun1(); // Returning to here now
Global Frame: fun1: pointer to memory address fun2: pointer to memory address tmpVal: 3 returnTo: null |
After this, the program terminates.
The Heap
- The Heap is for general data storage.
- ALL Objects are stored on the heap.
- There is no storage pattern enforcement (unlike the stack which is a data-structure called a stack).
- We rely on "garbage collection" to free memory on the heap.
The Heap
function fun1() {
var a = {
p1: 1,
p2: "text",
};
return a;
}
var b = fun1();
debugger;
... somewhere in the heap ...
p1: a
p2: "text"
The Stack will contain the value for b -- which is a pointer to this data somewhere in the heap!
Garbage Collection
Because the heap doesn't have a specific pattern for memory allocation, we have to do more work to "free" the memory allocated.
Garbage Collection
In older languages, this was done manually by programmers!
char *str;
/* Initial memory allocation */
str = (char *) malloc(15);
/* Reallocating memory */
str = (char *) realloc(str, 25);
/* Free the space */
free(str);
Garbage Collection
In modern languages a separate program called "the garbage collector" periodically searches for objects that no longer have any pointers pointing at them
function fun1() {
var a = {
p1: 1,
p2: "text",
};
return a;
}
console.log(fun1());
// At this point there is
// no way to access 'a'
Garbage Collection
After the console.log statement completes, there is no reference to the object we called 'a'. The Garbage Collector will find it, and free it's space on the heap.
function fun1() {
var a = {
p1: 1,
p2: "text",
};
return a;
}
console.log(fun1());
... somewhere in the heap ...
p1: a
p2: "text"
Garbage Collection
After the console.log statement completes, there is no reference to the object we called 'a'. The Garbage Collector will find it, and free it's space on the heap.
function fun1() {
var a = {
p1: 1,
p2: "text",
};
return a;
}
console.log(fun1());
... somewhere in the heap ...
Questions?
Memory Management
By Tyler Bettilyon
Memory Management
- 1,685