ruby-sdk icon indicating copy to clipboard operation
ruby-sdk copied to clipboard

[FSSDK-11776] fixing memory leak with project

Open alexjoeyyong opened this issue 3 months ago • 0 comments

Summary

This pull request introduces a robust caching mechanism to the Optimizely::Project class to prevent memory leaks caused by repeated SDK initialization, especially in high-throughput environments (like Rails apps). It adds a static instance cache, ensures proper cleanup of background threads, and provides new APIs for cache management. Extensive tests and documentation are included to guarantee safe usage and clarify best practices.

Key changes include:

Memory Leak Prevention & Caching Logic

  • Introduced a class-level instance cache in Optimizely::Project, with thread-safe access, to ensure that repeated initialization with the same static datafile returns the same instance, preventing unbounded thread growth and memory leaks. Instances are only cached for static datafile configurations and not for dynamic options (e.g., sdk_key, custom managers, etc.).
  • Added .get_or_create_instance, .clear_instance_cache!, and .cached_instance_count APIs to manage cached instances, and ensured that closing an instance removes it from the cache [1] [2].

Resource Cleanup & Thread Management

  • Implemented a finalizer using ObjectSpace.define_finalizer to ensure background threads (config_manager, event_processor, odp_manager) are cleaned up even if close is not called explicitly, further reducing risk of leaks.
  • Updated the close method to remove the instance from the cache and stop all background resources safely.

Testing & Safety Guarantees

  • Added comprehensive specs in spec/project_caching_spec.rb and spec/memory_leak_prevention_spec.rb to verify caching logic, proper resource cleanup, thread stability, and to ensure that only safe configurations are cached [1] [2].

Documentation

  • Added a new .github/copilot-instructions.md file detailing the SDK architecture, memory safety best practices, and correct usage patterns to prevent memory leaks in production environments.

These improvements make the SDK safer for production use, especially in multi-threaded and long-running server environments.


Memory leak prevention and caching:

  • Added class-level instance cache and .get_or_create_instance API to Optimizely::Project for safe reuse of static datafile configurations, preventing memory leaks from repeated initialization.
  • Ensured only safe configurations are cached (static datafile, no dynamic options), and provided APIs for clearing and monitoring the cache.

Resource cleanup and thread management:

  • Added a finalizer to clean up background threads if close is not called, and updated close to remove the instance from the cache [1] [2].

Testing and safety guarantees:

  • Introduced new specs to verify caching, thread stability, correct cleanup, and memory safety in various usage patterns (spec/project_caching_spec.rb, spec/memory_leak_prevention_spec.rb) [1] [2].

Documentation and usage guidance:

  • Added .github/copilot-instructions.md with architecture overview, memory leak prevention advice, and best practices for safe SDK usage.

Test plan

Pass automated tests

Issues

alexjoeyyong avatar Aug 22 '25 13:08 alexjoeyyong