• RPG Maker VX的Cache模块的几个小不足


    Cache在RMVX中主要负责储存读取过的Bitmap,源码的注释如下

    # ■ Cache
    #------------------------------------------------------------------------------
    #  本模组载入所有图像,建立并保存Bitmap物件。为加快载入速度并节省内存,
    #  本模组将以建立的bitmap物件保存在内部哈希表中,使得程序在需求已存在
    #  的图像时能快速读取bitmap物件。

    Cache模块的重要度自不用说。

    如果没有这个模块将bitmap物件保存到哈希表的话,我们不得不对自己生成的每一个bitmap手动dispose,否则程序很会快的吃掉所有内存崩溃。

    Cache中最关键的方法如下

      #--------------------------------------------------------------------------
      # * 载入图档
      #--------------------------------------------------------------------------
      def self.load_bitmap(folder_name, filename, hue = 0)
        @cache = {} if @cache == nil
        path = folder_name + filename
        if not @cache.include?(path) or @cache[path].disposed?
          if filename.empty?
            @cache[path] = Bitmap.new(32, 32)
          else
            @cache[path] = Bitmap.new(path)
          end
        end
        if hue == 0
          return @cache[path]
        else
          key = [path, hue]
          if not @cache.include?(key) or @cache[key].disposed?
            @cache[key] = @cache[path].clone
            @cache[key].hue_change(hue)
          end
          return @cache[key]
        end
      end

    该方法的主要目的是根据要读取的folder_name和filename拼凑出path,之后把path当做key检查内部哈希表是否已经保存过此bitmap物件

    如果已有则返回此物件,否则生成此物件后将其保存进哈希表并返回。

    一眼看过去没什么问题,但是有一点小的不足。

    假设我们用如下方式调用了两次这个方法

    bitmap1 = Cache.load_bitmap("Graphics/picture/", "aaa")
    bitmap2 = Cache.load_bitmap("Graphics/picture/", "AAA")

    显然,aaa和AAA指的是同一文件,但是两次读取的path并不相同,根本原因就是filename一个是大写一个是小写,从而导致path的不同。

    这样的话,Cache会在内部哈希表中保存两个其实一模一样的bitmap物件,如果你的这张图片不巧在1M左右,这样就会浪费掉大量内存。

    虽然我们可以强制自己在调用时的全部用小写输入,但难免疏忽,所以我们可以简单处理一下path,将其全部转为大写或者小写即可。

    另外,也许由于年代问题,rmvx当时还是直接使用String进行hash的,我们知道Symbol可以节约内存并加快读取速度,所以我们可以把其转为Symbol再哈希。

    最后的load_bitmap方法如下

      def self.load_bitmap(folder_name, filename, hue = 0)
        @cache = {} if @cache == nil
        path = (folder_name + filename).downcase
        sym = path.to_sym
        if not @cache.include?(sym) or @cache[sym].disposed?
          if filename.empty?
            @cache[sym] = Bitmap.new(32, 32)
          else
            @cache[sym] = Bitmap.new(path)
          end
        end
        if hue == 0
          return @cache[sym]
        else
          key = [sym, hue]
          if not @cache.include?(key) or @cache[key].disposed?
            @cache[key] = @cache[sym].clone
            @cache[key].hue_change(hue)
          end
          return @cache[key]
        end
      end
  • 相关阅读:
    python 字符串替换功能 string.replace()可以用正则表达式,更优雅
    windows 10 如何设定计划任务自动执行 python 脚本?
    win10 设定计划任务时提示所指定的账户名称无效,如何解决?
    pandas数据分析输出excel产生文本形式存储的百分比数据,如何处理?
    coinmarketcap前20之cardano卡尔达诺(ADA艾达币)
    【SpringMVC】参数绑定
    【SpringMVC】入门
    【Hibernate】 二级缓存及查询缓存
    【Hibernate】事务处理
    【Hibernate】抓取策略
  • 原文地址:https://www.cnblogs.com/deadblue/p/2827935.html
Copyright © 2020-2023  润新知