Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion apps/common/config/embedding_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,31 @@
from common.cache.mem_cache import MemCache

_lock = threading.Lock()
locks = {}


class ModelManage:
cache = MemCache('model', {})
up_clear_time = time.time()

@staticmethod
def _get_lock(_id):
lock = locks.get(_id)
if lock is None:
with _lock:
lock = locks.get(_id)
if lock is None:
lock = threading.Lock()
locks[_id] = lock

return lock

@staticmethod
def get_model(_id, get_model):
model_instance = ModelManage.cache.get(_id)
if model_instance is None:
with _lock:
lock = ModelManage._get_lock(_id)
with lock:
model_instance = ModelManage.cache.get(_id)
if model_instance is None:
model_instance = get_model(_id)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your code contains some potential improvements and fixes:

  1. Memory Locks Management: The current implementation uses a locks dictionary to store per-lock instances. However, you can simplify it using a nested locking mechanism within the _get_lock method.

  2. Concurrency Issues: Using a global lock (_lock) for managing memory locks might lead to contention. Instead, consider using a thread local lock or using Python's built-in synchronization primitives more effectively.

  3. Caching Logic: The caching logic is already optimized to avoid unnecessary computations and redundant requests. This part seems correct, but ensure that the MemCache object correctly handles invalidation times (e.g., setting keys expiring after a certain period).

  4. Synchronization: Ensure that all operations involving modifying the cache dictionary are protected by appropriate locks. Currently, only read operations use locking, which is fine.

Here is an improved version of your code:

from common.cache.mem_cache import MemCache
import threading

_lock = threading.Lock()

class ModelManage:
    cache = MemCache('model', {})
    up_clear_time = time.time()

    @staticmethod
    def get_model(_id, get_model):
        with _lock:
            # First try to retrieve from cache
            model_instance = ModelManage.cache.get(_id)
            
            if model_instance is None:
                # If not in cache, fetch from outside source and put into cache
                model_instance = get_model(_id)
                
                # Put the fetched model instance into cache
                ModelManage.cache.set(_id, model_instance)

        return model_instance

Key Improvements:

  • Removed the locks dictionary since each lock operation will manage its own context within the _get_lock method.
  • Simplified the locking strategy inside ModelManage.get_model.
  • Ensured consistent usage of with _lock: to handle exceptions properly during critical sections of code.

This should improve efficiency and reduce concurrency risks while maintaining simplicity in the design.

Expand Down