最近换了工作,改做建站软件了,我们公司建站软件的模板系统出了问题,提示内存超出最大值。内存的问题最简单的方法是修改php.ini提高memory_limit,但是随着模板数的不断增加,需要的内存又超出了上限,于是老大把这个问题让我看看,看我有什么好办法。
我拿到这个问题,首先是看懂原有的代码思路,分析问题产生的主要原因,出问题的页面很简单,就是一个模板显示页面,每页显示16个模板,做分页处理,而后台的处理却不简单,首先模板数据不是从数据库读取,而是从服务器端获取一个序列化字符串,取出的是所有的模板的信息数组,然后将信息缓存下来(以后先读缓存),然后数组中做过滤和分页操作,取出16个模板显示。
然后分析问题,很明显这里的问题是出在取出的是所有的模板的信息数组这个问题上,模板的数量是庞大的,但是其实每页需要的只有16个而已,可是这里却实现全部加入了内存。
问题时找到了,那怎么解决呢?于是我问了以前的员工,听他们的意见。他们提供了很多意见,有把模板放到数据库处理,有将分页等操作全部放到我们的服务器处理等,但是方案都需要对我们后台服务器做大的处理改进,而且改动的东西太大,引入的问题就多了,怎么办?
1. 惰性加载
后来我想,既然问题出在序列化取出了所有的数据,如果我们能在文件中,只取出我们需要的数据就好了,由于我有java的经验,我首先想到的是XML SAX 处理方式,但是我对PHP中XML处理不熟,不得要领。
不过却给了我正确的思路,很多的PHP内存过大的问题,是由于PHP开发者为了方便,将所有需要的数据预先加载到内存(array),然后通过处理,这样导致的问题是所需的内存远远超过了其实际的所需,导致了内存过量的问题。解决方法就是惰性加载,让数据在使用时才加载到内存中处理。
这里的问题很明显是序列化的问题,PHP的serialize机制是一个预先加载的策略,不支持惰性加载。需要找一个支持惰性加载的序列化方式,能够每次只读取一个模板的内容处理,很快CSV格式就出现了,CSV就支持这种以行为单位的读取方式,而对于原有的系统机制不需要有大的改动,于是就要对原有的系统进行csv序列化改变。
2.Iterator接口使用
csv读取使用while来遍历,而原来的系统使用数组来遍历,由于系统代码过滤的条件多,涉及很多代码的修改,而以前的数组使用key=>value对实现,而csv只能使用0,1,2数字访问。为了尽可能减少原有的代码修改,我们首先对csv做了处理,让它的第一行array的key值,从第二行开始显示模板实际数值value,位置和key一一对应,这样也满足了以后的扩展性。
为了和原代码的foreach风格尽量吻合,我们使用了Iterator封装了csv的操作,并在里面完成了csv的key->value的合并。这样,对于代码的迁移几乎可以忽略不计了,更大的好处是csv文件的大小比序列化后的文件大小下了很多,可能有人担心性能问题。
经过测试我们现有模板2000条,速度没有超过1秒,未来模板数要增加到20000条,遍历速度没有超过2s,也在可以接受的范围。于是这个问题就解决了。
最近,我们的自制简单的ORM框架出现了内存超过最大值,原因也是将所有数据库的值放入内存数组,于是我一手拿着惰性加载的矛,一手拿着Iterator的盾,又一次进入了解决问题之战争中。
分享到:
相关推荐
通过本文档提供的代码示例,我们将深入探讨`<s:iterator>`标签的使用方法及其与不同数据类型(如简单对象、列表、数组)的交互方式。 ### 一、`<s:iterator>`标签的基本用法 `<s:iterator>`标签允许你在JSP页面上...
总结来说,这个实例展示了如何在Java中使用`Iterator`和`Iterable`接口处理自定义数据结构,并利用`JSONArray`将这些数据转换为JSON格式。这种技能对于开发需要处理大量数据和进行数据交换的Java应用至关重要。理解...
首先,C++标准库定义了五种不同类型的迭代器:输入迭代器(Input Iterator)、输出迭代器(Output Iterator)、前向迭代器(Forward Iterator)、双向迭代器(Bidirectional Iterator)和随机访问迭代器(Random ...
使用 Iterator 接口遍历集合元素 Java 集合框架中的 Iterator 接口是一种非常重要的接口,它主要用于遍历集合中的元素。Iterator 接口隐藏了各种 ...但是,需要正确地使用 Iterator,避免引发异常和潜在的问题。
通过本文的学习,读者将能够更好地理解和掌握`Iterator`的用法。 #### 一、基本概念与使用方法 ##### 1. `Iterator`接口简介 `Iterator`接口定义了用于访问集合元素的方法,包括获取下一个元素、检查是否还有更多...
### Struts2中Iterator标签的深入解析与应用 ...掌握`<s:iterator>`的使用方法,对于提高Web应用程序的开发效率和维护性至关重要。通过灵活运用其各种属性和OGNL表达式,开发者可以构建出更加动态和响应式的用户界面。
要使用`iterator_adaptor`,你需要定义一个派生类,该派生类继承自`iterator_adaptor`的实例化。派生类通常会重写`iterator_facade`的一些核心接口函数,以适应基础迭代器(Base type)的行为。基础迭代器必须至少...
在给定的文档中,作者提到在处理JSOM、XML、Java bean等对象时,虽然访问者模式很常见,但在某些情况下,访问者模式可能不便于控制回调逻辑,这时可以使用Iterator模式来解决。 具体到文档内容,`StringGenerator`...
总的来说,Iterator模式提供了一种灵活且强大的方式来遍历和表示对象结构,尤其在需要对复杂对象进行深度分析和调试时,它能有效地提升代码的可读性和维护性。在实际开发中,根据需求选择合适的迭代器实现,可以大大...
在上述描述中,开发者遇到了一个关于`iterator`标签嵌套使用的问题,涉及到`LinkedHashMap`存储的数据结构。让我们深入探讨这个问题。 首先,`Timereport_infoAction`类中有几个关键的属性,包括`timereport_infos`...
"for、foreach、iterator的用法和区别" 在 Java 编程语言中,for、foreach 和 iterator 是三种常用的遍历数组和集合的方法。它们之间有相似之处,但也存在着许多不同之处。 相同点:三者都可以用来遍历数组和集合...
ArrayList提供了一种高效的方式来管理大量的元素,并且提供了迭代器(Iterator)来遍历这些元素,使得我们可以在不暴露底层实现细节的情况下访问和修改列表中的元素。这个资源的目的是通过模拟Java ArrayList的...
该文档是演示迭代器Iterator的使用方法和源代码,其中包括了Iterator的继承类的讲解和再Iterator中的两种方法
### WebWork Iterator 标签 Status 属性使用方法详解 在Web开发中,处理列表数据时经常需要用到迭代器来遍历并展示数据。...通过合理利用`<ww:iterator>`标签和status属性,我们可以使Web应用更加美观且易于维护。
### Iterator迭代器详解 #### 一、Iterator简介与概念 在Java编程语言中,`Iterator`接口是一个重要的组件,...无论是从设计模式的角度还是实际应用的角度来看,掌握`Iterator`的工作原理和使用方法都是非常重要的。
Iterator模式是C++编程中不可或缺的一部分,尤其是在使用STL时。它不仅提高了代码的可复用性和可维护性,还增强了程序的灵活性和扩展性。通过将容器的迭代逻辑封装在Iterator中,我们得以将关注点分离,让算法更专注...
本文将深入探讨`Iterator`的基本概念、使用方法以及其实现原理,帮助读者更好地理解和使用这一强大的工具。 #### 二、`Iterator`接口介绍 `Iterator`接口位于`java.util`包中,是集合框架的一部分。它定义了三个...
Iterator接口和ListIterator接口的使用可以带来很多便利,例如,使用Iterator接口可以遍历集合中的元素,而不管集合的具体实现类型,同时也可以使用ListIterator接口来控制迭代器的行为,例如,添加或删除元素。...
在`Main.java`文件中,通常会有测试代码,创建`BookShelf`对象,添加书籍,然后使用`Iterator`遍历并打印书架上的书籍。 在设计和实现`Iterator`时,有几点需要注意: 1. **线程安全**:如果你的迭代器需要在多...
在Java编程语言中,迭代器(Iterator)是一个至关重要的工具,它提供了一种高效且简洁的方式来遍历和访问集合中的元素,而无需暴露集合的内部结构。迭代器设计模式遵循了“访问者”模式的原则,使得代码更加灵活和可...