10

के माध्यम से कचरा-एकत्रित कैश जेएस में बड़ी वस्तुओं को कैश करना चाहता हूं। इन वस्तुओं को कुंजी द्वारा पुनर्प्राप्त किया जाता है, और उन्हें कैश करने का अर्थ होता है। लेकिन वे एक ही समय में स्मृति में फिट नहीं होंगे, इसलिए मैं चाहता हूं कि उन्हें आवश्यक होने पर कचरा इकट्ठा किया जाए - जीसी स्पष्ट रूप से बेहतर जानता है।जावास्क्रिप्ट WeakMaps

अन्य भाषाओं में वीक रेफरेंस या वीकवेल्यू डिक्शनरी का उपयोग करके ऐसा कैश बनाने के लिए बहुत छोटा है, लेकिन ईएस 6 में हमारे पास वीकैप है, जहां कुंजी कमजोर हैं।

तो, क्या WeakReference जैसे कुछ बनाना संभव है या WeakMap से कचरा एकत्रित कैश बनाना संभव है?

उत्तर

2

क्या वीकैप से वीक रेफरेंस बनाना संभव है या वीकैप से कचरा एकत्रित कैश बनाना संभव है?

AFAIK उत्तर दोनों प्रश्नों के लिए "नहीं" है।

4

जहां यह उपयोगी है के लिए एक हैश नक्शा कमजोर हो दो स्थितियों रहे हैं (तुम्हारा दूसरा फिट करने के लिए लगता है):

  1. एक एक ज्ञात पहचान के साथ एक वस्तु जानकारी शामिल करते हैं करना चाहती है; यदि ऑब्जेक्ट अस्तित्व में रहता है, तो संलग्न जानकारी अर्थहीन हो जाएगी और इसी तरह अस्तित्व में रहना चाहिए। जावास्क्रिप्ट इस परिदृश्य का समर्थन करता है।

  2. भंडारण आवश्यकताओं को कम करने और तुलना में तेजी लाने के प्रयोजनों के लिए, अर्थात् समान रूप से समान वस्तुओं के संदर्भों को मर्ज करना चाहता है। समान बड़े उपट्रीज़ के कई संदर्भों को प्रतिस्थापित करना, उदाहरण के लिए, एक ही उपट्री के संदर्भों के साथ स्मृति उपयोग और निष्पादन समय में क्रम-आयाम में कमी की अनुमति हो सकती है। दुर्भाग्यवश जावास्क्रिप्ट इस परिदृश्य का समर्थन नहीं करता है।

दोनों मामलों में, तालिका में संदर्भ जब तक जीवित रखा जाएगा के रूप में वे उपयोगी होते हैं, और जब वे बेकार हो जाते हैं "स्वाभाविक रूप से" संग्रह के लिए योग्य हो जाएगी। दुर्भाग्यवश, ऊपर परिभाषित दो उपयोगों के लिए अलग-अलग वर्गों को लागू करने के बजाय, WeakReference के डिजाइनरों ने इसे बनाया ताकि यह थोड़ी अच्छी तरह से नहीं हो सकता है, हालांकि यह थोड़ी-बहुत अच्छी तरह से उपयोग करने योग्य नहीं हो सकता है।

ऐसे मामलों में जहां कुंजी समानता परिभाषित करने के लिए समानता परिभाषित करती हैं, WeakHashMap पहले उपयोग पैटर्न को पूरा करेगा, लेकिन दूसरा अर्थहीन होगा (कोड जो किसी ऑब्जेक्ट का संदर्भ रखता है जो एक संग्रहीत कुंजी के समान रूप से समान होता है संग्रहीत कुंजी के संदर्भ में, और इसे देने के लिए WeakHashMap की आवश्यकता नहीं होगी)। ऐसे मामलों में जहां चाबियाँ समानता के किसी अन्य रूप को परिभाषित करती हैं, आमतौर पर संग्रहित ऑब्जेक्ट के संदर्भ के अलावा किसी भी अन्य तालिका को वापस करने के लिए तालिका क्वेरी के लिए यह समझ में नहीं आता है, लेकिन संग्रहित संदर्भ रखने से बचने का एकमात्र तरीका कुंजी को जीवंत रखना है WeakHashMap<TKey,WeakReference<TKey>> का उपयोग करें और क्लाइंट को कमजोर संदर्भ पुनर्प्राप्त करें, उसमें संग्रहीत मुख्य संदर्भ पुनर्प्राप्त करें, और जांचें कि यह अभी भी वैध है या नहीं, यह WeakHashMapWeakReference पर लौटाता है और WeakReference स्वयं की जांच हो जाती है)।

+0

मुझे लगता है कि इस सवाल का विशेष रूप से जावास्क्रिप्ट, नहीं जावा या जो 'WeakReference' /' WeakHashMap' कुछ अन्य भाषा के लिए बात कर रहा है। समस्या यह है कि जावास्क्रिप्ट में केवल 'वीक हैशमैप' जैसा कुछ है, लेकिन 'वीक रेफरेंस' के बराबर नहीं है। –

+0

@ Qantas94Heavy: वास्तव में ऐसा है। शायद मुझे यह संकेत देना चाहिए था कि जावास्क्रिप्ट केवल पहले का समर्थन करता है, दुर्भाग्य से ऐसा नहीं है कि मुझे संदेह है कि ओपी वास्तव में चाहता है। क्या आपको संपादन पसंद है? – supercat

0

जैसा कि अन्य उत्तरों का उल्लेख है, दुर्भाग्य से कमजोर मानचित्र जैसी कोई चीज़ नहीं है, जैसे जावा/सी # में है।

के चारों ओर एक काम के रूप में, मैं इस CacheMap कि चारों ओर की वस्तुओं की अधिकतम संख्या रहता है बनाया है, और समय की एक निर्धारित अवधि में उनके उपयोग को ट्रैक करता है ताकि आप:

  1. हमेशा कम से कम पहुँचा वस्तु निकालने के लिए, जब आवश्यक
  2. मेमोरी रिसाव न बनाएं।

यहां कोड है।

"use strict"; 

/** 
* This class keeps a maximum number of items, along with a count of items requested over the past X seconds. 
* 
* Unfortunately, in JavaScript, there's no way to create a weak map like in Java/C#. 
* See https://stackoverflow.com/questions/25567578/garbage-collected-cache-via-javascript-weakmaps 
*/ 
module.exports = class CacheMap { 
    constructor(maxItems, secondsToKeepACountFor) { 
    if (maxItems < 1) { 
     throw new Error("Max items must be a positive integer"); 
    } 
    if (secondsToKeepACountFor < 1) { 
     throw new Error("Seconds to keep a count for must be a positive integer"); 
    } 

    this.itemsToCounts = new WeakMap(); 
    this.internalMap = new Map(); 
    this.maxItems = maxItems; 
    this.secondsToKeepACountFor = secondsToKeepACountFor; 
    } 

    get(key) { 
    const value = this.internalMap.get(key); 
    if (value) { 
     this.itemsToCounts.get(value).push(CacheMap.getCurrentTimeInSeconds()); 
    } 
    return value; 
    } 

    has(key) { 
    return this.internalMap.has(key); 
    } 

    static getCurrentTimeInSeconds() { 
    return Math.floor(Date.now()/1000); 
    } 

    set(key, value) { 
    if (this.internalMap.has(key)) { 
     this.internalMap.set(key, value); 
    } else { 
     if (this.internalMap.size === this.maxItems) { 
     // Figure out who to kick out. 
     let keys = this.internalMap.keys(); 
     let lowestKey; 
     let lowestNum = null; 
     let currentTime = CacheMap.getCurrentTimeInSeconds(); 
     for (let key of keys) { 
      const value = this.internalMap.get(key); 
      let totalCounts = this.itemsToCounts.get(value); 
      let countsSince = totalCounts.filter(count => count > (currentTime - this.secondsToKeepACountFor)); 
      this.itemsToCounts.set(value, totalCounts); 
      if (lowestNum === null || countsSince.length < lowestNum) { 
      lowestNum = countsSince.length; 
      lowestKey = key; 
      } 
     } 

     this.internalMap.delete(lowestKey); 
     } 
     this.internalMap.set(key, value); 
    } 
    this.itemsToCounts.set(value, []); 
    } 

    size() { 
    return this.internalMap.size; 
    } 
}; 

और आप इसे इतना पसंद किया फोन:

// Keeps at most 10 client databases in memory and keeps track of their usage over a 10 min period. 
let dbCache = new CacheMap(10, 600); 
संबंधित मुद्दे