| Scale | Number of Objects | Memory Usage | Performance Impact | Notes |
|---|---|---|---|---|
| 100 Objects | All unique or few shared | Low to moderate | Fast, no memory issues | Flyweight may not be needed |
| 10,000 Objects | Many duplicates, shared flyweights | Moderate | Memory savings noticeable | Flyweight reduces memory footprint |
| 1,000,000 Objects | High duplication, many shared flyweights | High without flyweight, moderate with | Memory bottleneck without flyweight | Flyweight critical for memory efficiency |
| 100,000,000 Objects | Extensive sharing required | Very high without flyweight, manageable with | CPU overhead for managing flyweights | Flyweight pattern essential, caching strategies needed |
Flyweight pattern in LLD - Scalability & System Analysis
Memory usage is the first bottleneck as the number of objects grows. Without the flyweight pattern, each object stores its own data, causing high memory consumption. This leads to slower performance and possible crashes due to memory exhaustion.
- Flyweight Pattern: Share common intrinsic state among objects to reduce memory.
- Object Pooling: Reuse objects to avoid frequent allocations.
- Caching: Cache flyweight instances to avoid recreating shared data.
- Lazy Initialization: Create flyweights only when needed to save resources.
- Horizontal Scaling: Distribute workload across multiple servers if CPU overhead grows.
Assuming each object without flyweight uses 1 KB memory:
- At 1,000 objects: ~1 MB memory
- At 1,000,000 objects: ~1 GB memory (may cause pressure)
- With flyweight, shared data reduces memory by ~90%, saving ~900 MB at 1,000,000 objects
CPU overhead for managing flyweights is low compared to memory savings.
Start by explaining the problem of memory usage with many similar objects. Then describe how flyweight shares intrinsic state to save memory. Discuss trade-offs like added complexity and CPU overhead. Finally, mention scaling solutions and when to apply them.
Your system creates 1,000 objects each using 1 KB memory. Traffic grows 10x to 10,000 objects. Memory usage grows to 10 MB, causing pressure. What do you do first?
Answer: Apply the flyweight pattern to share common data among objects, reducing memory usage and preventing memory bottleneck.
Practice
Flyweight pattern in system design?Solution
Step 1: Understand the Flyweight pattern goal
The Flyweight pattern focuses on reducing memory usage by sharing common data among many objects.Step 2: Compare options with the pattern goal
Only To save memory by sharing common parts of objects matches the purpose of saving memory by sharing parts of objects.Final Answer:
To save memory by sharing common parts of objects -> Option BQuick Check:
Flyweight = Memory sharing [OK]
- Confusing Flyweight with caching or encryption
- Thinking Flyweight creates new objects each time
- Mixing Flyweight with network optimization
Solution
Step 1: Recall Flyweight data separation
Flyweight stores intrinsic (shared) data internally and receives extrinsic (unique) data externally.Step 2: Match options with this rule
Store shared data inside the Flyweight and pass unique data externally correctly states shared data inside Flyweight and unique data passed externally.Final Answer:
Store shared data inside the Flyweight and pass unique data externally -> Option AQuick Check:
Intrinsic inside, extrinsic outside [OK]
- Putting unique data inside Flyweight causing duplication
- Not separating data leading to memory waste
- Confusing intrinsic and extrinsic states
class TreeType:
def __init__(self, name, color):
self.name = name
self.color = color
class TreeFactory:
_tree_types = {}
@classmethod
def get_tree_type(cls, name, color):
key = (name, color)
if key not in cls._tree_types:
cls._tree_types[key] = TreeType(name, color)
return cls._tree_types[key]
# Usage
factory = TreeFactory()
t1 = factory.get_tree_type('Oak', 'Green')
t2 = factory.get_tree_type('Oak', 'Green')
t3 = factory.get_tree_type('Pine', 'Green')
print(t1 is t2, t1 is t3)What will be the output?
Solution
Step 1: Understand object sharing in factory
The factory returns the same TreeType object for identical (name, color) keys, so t1 and t2 share the same object.Step 2: Compare object identities
t1 is t2 will be True because they share the same instance; t1 is t3 will be False because 'Pine' differs from 'Oak'.Final Answer:
True False -> Option AQuick Check:
Shared keys = same object [OK]
- Assuming all objects are different
- Ignoring the factory cache
- Confusing identity (is) with equality (==)
class Flyweight:
def __init__(self, shared_state):
self.shared_state = shared_state
class FlyweightFactory:
def __init__(self):
self._flyweights = {}
def get_flyweight(self, shared_state):
if shared_state not in self._flyweights:
self._flyweights[shared_state] = Flyweight(shared_state)
return self._flyweights[shared_state]Solution
Step 1: Identify dictionary key usage
The code usesshared_stateas a dictionary key, but ifshared_stateis a mutable type like a list or dict, it cannot be used as a key.Step 2: Understand dictionary key requirements
Dictionary keys must be immutable and hashable; using mutable types causes runtime errors.Final Answer:
Using mutable type as dictionary key without hashing -> Option CQuick Check:
Dict keys must be immutable [OK]
- Ignoring type of shared_state as dict key
- Assuming Flyweight always stores unique data
- Overlooking constructor presence
Solution
Step 1: Identify intrinsic and extrinsic data
Font style and color are shared (intrinsic), position is unique (extrinsic) for each character.Step 2: Apply Flyweight pattern correctly
Create Flyweight objects for shared font and color, pass position externally when rendering characters.Final Answer:
Create a Flyweight object for each unique character with its font and color, pass position externally -> Option DQuick Check:
Shared data in Flyweight, unique data outside [OK]
- Putting position inside Flyweight causing many objects
- Not sharing font and color data
- Ignoring separation of intrinsic and extrinsic data
Ready to prove it?
Pass the test and this pattern moves unknown
