當前位置:首頁 » 操作系統 » lrucache源碼

lrucache源碼

發布時間: 2022-08-02 08:19:54

㈠ android disklrucache怎麼使用

下面是一個簡單的DiskLruCache實現。然而推薦的實現DiskLruCache方案請參考Android4.0中(libcore/luni/src/main/java/libcore/io/DiskLruCache.java)源碼。本文使用的是之前版本中的簡單實現(Quick Search中是另外的實現).

顯示是簡單實現DiskLruCache更新後的例子:

private DiskLruCache mDiskCache;
private static final int DISK_CACHE_SIZE = 1024 * 1024 * 10; // 10MB
private static final String DISK_CACHE_SUBDIR = "thumbnails";

@Override
protected void onCreate(Bundle savedInstanceState) {
...
// Initialize memory cache
...
File cacheDir = getCacheDir(this, DISK_CACHE_SUBDIR);
mDiskCache = DiskLruCache.openCache(this, cacheDir, DISK_CACHE_SIZE);
...
}

class BitmapWorkerTask extends AsyncTask {
...
// Decode image in background.
@Override
protected Bitmap doInBackground(Integer... params) {
final String imageKey = String.valueOf(params[0]);

// Check disk cache in background thread
Bitmap bitmap = getBitmapFromDiskCache(imageKey);

if (bitmap == null) { // Not found in disk cache
// Process as normal
final Bitmap bitmap = (
getResources(), params[0], 100, 100));
}

// Add final bitmap to caches
addBitmapToCache(String.valueOf(imageKey, bitmap);

return bitmap;
}
...
}

public void addBitmapToCache(String key, Bitmap bitmap) {
// Add to memory cache as before
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}

// Also add to disk cache
if (!mDiskCache.containsKey(key)) {
mDiskCache.put(key, bitmap);
}
}

public Bitmap getBitmapFromDiskCache(String key) {
return mDiskCache.get(key);
}

// Creates a unique subdirectory of the designated app cache directory. Tries to use external
// but if not mounted, falls back on internal storage.
public static File getCacheDir(Context context, String uniqueName) {
// Check if media is mounted or storage is built-in, if so, try and use external cache dir
// otherwise use internal cache dir
final String cachePath = Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED
|| !Environment.isExternalStorageRemovable() ?
context.getExternalCacheDir().getPath() : context.getCacheDir().getPath();

return new File(cachePath + File.separator + uniqueName);
}
內存緩存檢查在UI線程中做,磁碟緩存的檢查在後台線程中。硬碟操作不應在UI線程中。圖片處理完成後應將其加入正在使用的內存、磁碟緩存中。

㈡ 使用ExpandableListView以及怎麼優化view的顯示減少內存佔用

解決方案Github pull request鏈接:
Android的原生提供和展開分組的ListView:ExpandableListView,然而相比於iOS上原生提供的UITableView,其UI能力不足,比如沒有原生的動畫展開和收起效果支持。
在開源代碼社區我們可以找到幾個為Android的ExpandableListView添加的動畫解決方案。其中innololz的AnimatedExpandableListView是不錯的方案之一。 。它的優點:性能較好,提供源代碼而不是library(這點很重要),注釋清晰。
然而性能的優化是沒有止境的,當分組內的子view(childView)變得復雜,或者ListView的parent結構復雜,例如內嵌與其它LinearLayout, FrameLayout或者ScrollView之中,並且parent的使用自定義的重寫的onMeasure()方法時,生成childView的效率就會大大影響應用的性能。
合理使用AnimatedExpandableListView的關鍵是在於AnimatedExpandableListView#getRealChildView()的實現,這是應用開發的責任。實際項目中,通過優化getRealChildView(),動畫效果的啟動時間從1340ms減少到了680ms (展開一個含有5個子項目的分組)。而發現的問題的定位和解決方案,基本是用過使用Android提供的method tracing方法(android.os.Debug.startMethodTraceing)進行分析。
優化前的getRealChildView()實現,需要大量的view初始化,因為沒有可用的convertView,而事實上,在動畫繪制階段時生成的childView完全可以被重用,及時convertView並為給出。如下面的traceview profile看到的,優化前,getChildView()消耗了超過一秒的時間。

優化後的性能:

這是如何做到的呢?這需要我們再研究一下動畫展開的原理,也就是getChildView()裡面耗時最長的是哪些動作。首先排除其他因素的影響,專注於AnimatedExpandableList本收得使用,我們使用GitHub上原生提供的Example來做分析:這是展開5個子項目的分組的情況,注意5個子分組的view生成,LayoutInflater.inflate被執行了10次,是其兩倍。而inflate是相當耗時的。有沒有方法來減少這部分工作消耗呢?

方法是使用Android推薦的LRU cache來保存childView的。關於LruCache,請見Android的reference documents和training。這里特別要注意的是,childView在dataSet改變時需要重新生成,而不是在cache中獲得,這里使用的方法是判斷childView的type。在自己的項目中需要根據情況認真考慮dataSet改變如何更新cache的問題。效果如下所示:inflate的次數減少到5次,一次都不浪費。消耗時間從160ms降低到80ms。

㈢ Android培訓課程有什麼內容

第一階段的課程一般都是Java編程開發

這一部分應該會和Java後台有相關聯的地方,但是比Java後台簡單,這一階段一般要學習Java語法和Java面向對象思想、Java數據結構及演算法、GUI界面編程、Java進程與線程、Java網路通信與流、設計模式、資料庫和Javaweb,安卓在這一階段的學習內容看似和後台關聯性很大,但是這一部分我們只學習後台一些基礎的東西和日後會用到的東西,我們要把基礎奠定好。

第二階段要學習的內容是安卓基礎開發

主要的課程內容為Android界面編程(界面編程是Android入門的核心技術,內容縱多,涉及四大組件之一Activity、Wedget、自定義View、事件處理、動畫處理、列表、圖片處理、國際化、資源文件、菜單、通知、對話框、Tools/ActionBar/Fragment、樣式/主題、Intent。)、進程與線程、服務與廣播、數據存儲、網路通信、多媒體以及硬體相關,這一階段更注重安卓入門基礎的培訓,一定要好好的把握。

接下來學習的內容是一個進階階段,主要學習的是安卓的高級開發,一般的課程內容為HOME開發、NDK開發等、地圖開發項目發布等等,以上就算是安卓培訓的所有學習內容,但是你掌握了學習內容之後還是遠遠不夠的,一般的培訓班都會給我們安排項目實戰的,這是一種思想的鍛煉,我們做什麼就要有什麼的思維做後台的有做後台的思維,做前端的有做前端的思維,我們學安卓的進行手機端APP開發的就要有安卓的思維,這一階段也是很重要的,就好比我們在華清遠見學完整體的內容之後也參與了一些項目的實戰。

我把每一階段要學習的課程都給你整理了,你可以現在有準備的去看一些基礎的視頻或者相關的書籍了。

安卓培訓視頻資料都有

㈣ android lruchache可以離線嗎

android lruchache不可以離線。cache的意思是緩存。
一、中央處理器。
中央處理器是電腦的心臟,由運算器和控制器組成,內部結構分為控制器、運算器和存儲器,這三個部分相互協調,可以進行判斷、運算和並控制電腦各部分協調工作。
二、中央處理器的核心。
目前流行的中央處理器為英特爾酷睿中央處理器,分為雙核、四核和八核。雙核中央處理器是基於單個半導體的一個處理器上擁有兩個一樣功能的處理器核心。
三、中央處理器的指標。
衡量中央處理器的指標是字長,字長是電腦能直接處理的二進制數據的位數,標志著電腦處理數據的能力,字長決定了電腦運算的能力和精度,字長越長,電腦的運算能力越強,精度越高,有效數據的存儲單元數越多,尋找地址的能力越強。現在個人電腦的字長分為十六位、三十二位和六十四位。
四、緩存。
可以進行高速數據交換的存儲器叫做緩存,也叫高速緩存。中央處理器一般會從緩存讀取數據,中央處理器沒有數據時才會向內存調用數據。緩存容量越大,中央處理器的性能越好。中央處理器的緩存分為一級緩存和二級緩存。酷睿處理器中,四個核心的內存控制器和緩存都在單一的晶元上面。

㈤ mybatis 二級緩存怎麼使用

深入了解MyBatis二級緩存
一、創建Cache的完整過程
我們從sqlSessionFactoryBuilder解析mybatis-config.xml配置文件開始:
Reader reader = Resources.getResourceAsReader("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);

然後是:
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());

看parser.parse()方法:
parseConfiguration(parser.evalNode("/configuration"));

看處理Mapper.xml文件的位置:
mapperElement(root.evalNode("mappers"));

看處理Mapper.xml的XMLMapperBuilder:
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration,
resource, configuration.getSqlFragments());
mapperParser.parse();

繼續看parse方法:
configurationElement(parser.evalNode("/mapper"));

到這里:
String namespace = context.getStringAttribute("namespace");
if (namespace.equals("")) {
throw new BuilderException("Mapper's namespace cannot be empty");
}
builderAssistant.setCurrentNamespace(namespace);
cacheRefElement(context.evalNode("cache-ref"));
cacheElement(context.evalNode("cache"));

從這里看到namespace就是xml中<mapper>元素的屬性。然後下面是先後處理的cache-ref和cache,後面的cache會覆蓋前面的cache-ref,但是如果一開始cache-ref沒有找到引用的cache,他就不會被覆蓋,會一直到最後處理完成為止,最後如果存在cache,反而會被cache-ref覆蓋。這里是不是看著有點暈、有點亂?所以千萬別同時配置這兩個,實際上也很少有人會這么做。
看看MyBatis如何處理<cache/>:
private void cacheElement(XNode context) throws Exception {
if (context != null) {
String type = context.getStringAttribute("type", "PERPETUAL");
Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
String eviction = context.getStringAttribute("eviction", "LRU");
Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
Long flushInterval = context.getLongAttribute("flushInterval");
Integer size = context.getIntAttribute("size");
boolean readWrite = !context.getBooleanAttribute("readOnly", false);
boolean blocking = context.getBooleanAttribute("blocking", false);
Properties props = context.getChildrenAsProperties();
builderAssistant.useNewCache(typeClass, evictionClass,
flushInterval, size, readWrite, blocking, props);
}
}

從源碼可以看到MyBatis讀取了那些屬性,而且很容易可以到這些屬性的默認值。
創建Java的cache對象方法為builderAssistant.useNewCache,我們看看這段代碼:
public Cache useNewCache(Class<? extends Cache> typeClass,
Class<? extends Cache> evictionClass,
Long flushInterval,
Integer size,
boolean readWrite,
boolean blocking,
Properties props) {
typeClass = valueOrDefault(typeClass, PerpetualCache.class);
evictionClass = valueOrDefault(evictionClass, LruCache.class);
Cache cache = new CacheBuilder(currentNamespace)
.implementation(typeClass)
.addDecorator(evictionClass)
.clearInterval(flushInterval)
.size(size)
.readWrite(readWrite)
.blocking(blocking)
.properties(props)
.build();
configuration.addCache(cache);
currentCache = cache;
return cache;
}

從調用該方法的地方,我們可以看到並沒有使用返回值cache,在後面的過程中創建MappedStatement的時候使用了currentCache。
二、使用Cache過程
在系統中,使用Cache的地方在CachingExecutor中:
@Override
public <E> List<E> query(
MappedStatement ms, Object parameterObject,
RowBounds rowBounds, ResultHandler resultHandler,
CacheKey key, BoundSql boundSql) throws SQLException {
Cache cache = ms.getCache();

獲取cache後,先判斷是否有二級緩存。
只有通過<cache/>,<cache-ref/>或@CacheNamespace,@CacheNamespaceRef標記使用緩存的Mapper.xml或Mapper介面(同一個namespace,不能同時使用)才會有二級緩存。
if (cache != null) {

如果cache存在,那麼會根據sql配置(<insert>,<select>,<update>,<delete>的flushCache屬性來確定是否清空緩存。
flushCacheIfRequired(ms);

然後根據xml配置的屬性useCache來判斷是否使用緩存(resultHandler一般使用的默認值,很少會null)。
if (ms.isUseCache() && resultHandler == null) {

確保方法沒有Out類型的參數,mybatis不支持存儲過程的緩存,所以如果是存儲過程,這里就會報錯。
ensureNoOutParams(ms, parameterObject, boundSql);

沒有問題後,就會從cache中根據key來取值:
@SuppressWarnings("unchecked")
List<E> list = (List<E>) tcm.getObject(cache, key);

如果沒有緩存,就會執行查詢,並且將查詢結果放到緩存中。
if (list == null) {
list = delegate.<E>query(ms, parameterObject,
rowBounds, resultHandler, key, boundSql);
tcm.putObject(cache, key, list); // issue #578 and #116
}

返回結果
return list;
}
}

沒有緩存時,直接執行查詢
return delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}

在上面的代碼中tcm.putObject(cache, key, list);這句代碼是緩存了結果。但是實際上直到sqlsession關閉,MyBatis才以序列化的形式保存到了一個Map(默認的緩存配置)中。

三、Cache使用時的注意事項
1. 只能在【只有單表操作】的表上使用緩存
不只是要保證這個表在整個系統中只有單表操作,而且和該表有關的全部操作必須全部在一個namespace下。
2. 在可以保證查詢遠遠大於insert,update,delete操作的情況下使用緩存
這一點不需要多說,所有人都應該清楚。記住,這一點需要保證在1的前提下才可以!

四、避免使用二級緩存
可能會有很多人不理解這里,二級緩存帶來的好處遠遠比不上他所隱藏的危害。
緩存是以namespace為單位的,不同namespace下的操作互不影響。
insert,update,delete操作會清空所在namespace下的全部緩存。
通常使用MyBatis Generator生成的代碼中,都是各個表獨立的,每個表都有自己的namespace。
為什麼避免使用二級緩存
在符合【Cache使用時的注意事項】的要求時,並沒有什麼危害。
其他情況就會有很多危害了。
針對一個表的某些操作不在他獨立的namespace下進行。
例如在UserMapper.xml中有大多數針對user表的操作。但是在一個XXXMapper.xml中,還有針對user單表的操作。
這會導致user在兩個命名空間下的數據不一致。如果在UserMapper.xml中做了刷新緩存的操作,在XXXMapper.xml中緩存仍然有效,如果有針對user的單表查詢,使用緩存的結果可能會不正確。
更危險的情況是在XXXMapper.xml做了insert,update,delete操作時,會導致UserMapper.xml中的各種操作充滿未知和風險。
有關這樣單表的操作可能不常見。但是你也許想到了一種常見的情況。
多表操作一定不能使用緩存
為什麼不能?
首先不管多表操作寫到那個namespace下,都會存在某個表不在這個namespace下的情況。
例如兩個表:role和user_role,如果我想查詢出某個用戶的全部角色role,就一定會涉及到多表的操作。
<select id="selectUserRoles" resultType="UserRoleVO">
select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
</select>123123

像上面這個查詢,你會寫到那個xml中呢??
不管是寫到RoleMapper.xml還是UserRoleMapper.xml,或者是一個獨立的XxxMapper.xml中。如果使用了二級緩存,都會導致上面這個查詢結果可能不正確。
如果你正好修改了這個用戶的角色,上面這個查詢使用緩存的時候結果就是錯的。
這點應該很容易理解。
在我看來,就以MyBatis目前的緩存方式來看是無解的。多表操作根本不能緩存。
如果你讓他們都使用同一個namespace(通過<cache-ref>)來避免臟數據,那就失去了緩存的意義。
看到這里,實際上就是說,二級緩存不能用。整篇文章介紹這么多也沒什麼用了。

五、挽救二級緩存?
想更高效率的使用二級緩存是解決不了了。
但是解決多表操作避免臟數據還是有法解決的。解決思路就是通過攔截器判斷執行的sql涉及到那些表(可以用jsqlparser解析),然後把相關表的緩存自動清空。但是這種方式對緩存的使用效率是很低的。
設計這樣一個插件是相當復雜的,既然我沒想著去實現,就不廢話了。
最後還是建議,放棄二級緩存,在業務層使用可控制的緩存代替更好。

㈥ disklrucache 怎麼讀

下面是一個簡單的DiskLruCache實現。然而推薦的實現DiskLruCache方案請參考Android4.0中(libcore/luni/src/main/java/libcore/io/DiskLruCache.java)源碼。

㈦ 如何引用第三方 resty 庫

和大部分知名開源軟體誕生在歐美國家不同,OpenResty自身和依賴的主要組件都是金磚國家的開發者發明的,這點還挺有意思。

Nginx是俄羅斯人發明的,Lua是巴西幾個教授發明的,中國人章亦春把LuaJITVM嵌入到Nginx中,實現了OpenResty這個高性能服務端解決方案。

通過OpenResty,你可以把nginx的各種功能進行自由拼接,更重要的是,開發門檻並不高,這一切都是用強大輕巧的Lua語言來操控。

它主要的使用場景主要是:

在Lua中揉和和處理各種不同的nginx上游輸出(Proxy,Postgres,Redis,Memcached等)
在請求真正到達上游服務之前,Lua可以隨心所欲的做復雜的訪問控制和安全檢測
隨心所欲的操控響應頭裡面的信息
從外部存儲服務(比如Redis,Memcached,MySQL,Postgres)中獲取後端信息,並用這些信息來實時選擇哪一個後端來完成業務訪問
在內容handler中隨意編寫復雜的Web應用,使用同步但依然非阻塞的方式,訪問後端資料庫和其他存儲
在rewrite階段,通過Lua完成非常復雜的URLdispatch
用Lua可以為nginx子請求和任意location,實現高級緩存機制

組織OpenResty技術大會之前,我一直認為自己是一個孤獨的OpenResty使用者,覺得自己在使用一個冷門的技術。

雖然大家都聽說過OpenResty或者ngx_lua,但感覺用在生產環境中使用的卻少之又少,除了幾個CDN公司外,好像沒有聽說過哪家知名互聯網公司在使用。而CDN行業之所以使用,很多是受到cloudflare技術棧的影響,OpenResty的作者也在國外這家CDN公司。

但辦完這個大會,我發現使用者真的挺多,奇虎360的所有服務端團隊都在使用,京東、網路、魅族、知乎、優酷、新浪這些互聯網公司都在使用。有用來寫WAF、有做CDN調度、有做廣告系統、消息推送系統,還有像我們部門一樣,用作APIserver的。有些還用在非常關鍵的業務上,比如開濤在高可用架構分享的京東商品詳情頁,是我知道的ngx_lua最大規模的應用。

2.奇虎企業安全服務端技術選型的標准

先說下3年多前做架構選型的時候,我為什麼會選擇OpenResty?

其實架構如何設計並不重要,因為每家公司,每個團隊,他們的公司文化和技術背景各不相同,生搬硬套會適得其反。重要的是當初為什麼這么選擇,中途為什麼調整。

我們的產品要求單機上面,服務端提供高性能的API介面,QPS至少過萬,未來需要支撐到10萬。我們並沒有急於去使用PHP、python或者其他的語言來實現功能,而是先勾勒出一個理想化的技術模型。

這個模型應該具備:

非阻塞的訪問網路IO。在連接MySQL、Redis和發起HTTP請求時,工作進程不能傻傻的等待網路IO的返回,而是需要支持事件驅動,用協程的方式讓CPU資源更有效的去處理其他請求。很多語言並不具備這樣的能力和周邊庫。

有完備的緩存機制。不僅需要支持Redis、Memcached等外部緩存,也應該在自己的進程內有緩存系統。我們希望大部分的請求都能在一個進程中得到數據並返回,這樣是最高效的方法,一旦有了網路IO和進程間的交互,性能就會受到很大影響。

同步的寫代碼邏輯,不要讓開發者感知到回調和非同步。這個也很重要,程序員也是人,代碼應該更符合人的思維習慣,顯式的回調和非同步關鍵字,會打斷思路,也給調試帶來困難。

最好是站在巨人肩上,基於成熟的技術上搭建。採用一門全新誕生的語言和技術,需要經歷語言自身發展期頻繁調整的陣痛,還可能站錯隊。

不僅支持Linux平台,還需要支持Windows平台,這個是我們產品很特別的需求,很多中小企業用戶還是習慣Windows的操作,不具備Linux的維護能力。

基於以上幾點的考慮,考察了當時的一些方案,選擇了OpenResty。

首先,它最大的特點就是用同步的代碼邏輯實現非阻塞的調用,其次它有單進程內的LRUcache和進程間的shareDICTcache,而且它是揉合nginx和LuaJIT而產生的。而且nginx有Windows版本,雖然有非常多的限制,但這些限制都是可以解決的,nginx官方Windows版本中不支持的特性,我們開源出來的版本都解決了。

第一次看到這樣的方案,我覺得它肯定會顛覆高性能服務端的開發。為什麼呢?在我之前的公司里,每天會有近百億次的查詢請求,而伺服器只用了十台。

我們採用了nginxC模塊+內置在nginx中的K-V資料庫(自己開發的),來實現所有的業務邏輯,達到這個目標。聽上去很簡單,但是過程非常艱辛,兩三個十幾年工作經驗的大牛做了一年多才穩定下來。絕大部分開發能力不足,只能望塵莫及。而且後續的調試和維護,也會花費不少精力。

但是OpenResty的出現改變了這一切,OpenResty非常的pythonic,適合人類的正常思維。新手經過一兩個月的學習,做出來的API,就可以達到nginxC模塊的性能,而且代碼量大大減少,也方便調試。

3.以奇虎和新浪為例,如何在項目中引入新技術

技術選型只是第一步,如何才能在一個產品或者項目中引入OpenResty這個新的技術呢?我拿奇虎企業安全和新浪移動這兩家公司真實發生的案例給大家看看。我和新浪移動的周晶,都是在一個有成熟產品的部門,用一兩個人的力量,把一個新技術,替換掉了原有的技術架構。但由於企業產品和個人產品的不同,方法有很大的不一樣。

先說我所在奇虎企業安全。我在2012年初加入這個部門,當時產品主打免費,目標用戶是小企業。所以架構設計上面,只考慮了幾十點、幾百點的終端請求,使用了非常強綁定的Windows平台技術,而且傾向於不用開源軟體,自己新做一個更適合自己的框架。包括自己用C++開發的Webserver,自己寫的PHP路由和框架,數據存儲在sqlite裡面。

我幫忙修改了兩個月PHP的bug,看明白了技術架構的思路之後,就去新開的一個產品線了。這是一個實驗性的產品,主要面對央企和專用網,一個網路中有上百萬的終端。

剛開始沒有什麼人關注,我就直接採用了Linux+OpenResty+Redis+Postgres的開源組件,性能測試甩之前的N條街。後面這個實驗性的產品,和之前的產品,合並為一個產品,技術上面就割裂為兩套架構。老功能用老架構,新功能用新架構。

隨著越來越多大用戶的增加,原有的技術架構開始捉襟見肘,技術債務越積壓越多。隨著用戶的抱怨,sqlite被拋棄,全面換成Postgres。但對於自己開發的框架還是有些敝帚自珍。

期間通過對比測試、OpenResty培訓還有多次用戶性能問題排查,讓開發同學們都知道這門技術的優勢。快被加班壓垮的開發同學,逐漸開始選擇使用OpenResty而不是自研的框架,來進行新功能的開發,以及舊功能的遷移,來避免加班。

在產品重構的時候,之前自研的服務端框架被完全拋棄,服務端開發的同學從8、9個人減少到3個人。在新技術的引入過程中,我們沒有採用強制的舉措,因為企業產品需要穩定,用戶處部署的版本更新很慢。

而新浪移動周晶的實踐,對大家更有參考意義。新浪移動最開始是基於Apache,用PHP來處理用戶請求。Apache是同步多進程模型,在並發請求不多的情況下沒有問題。

但是總是會有突發新聞,比如馬航失聯、文章出軌等,突發的高流量把後台壓垮了幾次。而且可以預見世界盃的流量也會很大,所以周晶花幾個月時間,用nginx替換了Apache,使用nginx的fast_cgi_cache,QPS提升了一個數量級。

新浪移動後台的介面都是使用PHP來實現的,在高並發下有些力不從心。而nginx簡單的緩存雖然能滿足性能,但不能滿足業務精細化和數據一致性的要求,需要找PHP之外的解決方案,前提是讓PHP的開發能夠舒適的使用。node.js的回調地獄、Go的調試不方便,都是一個阻礙。

他們最後選擇了OpenResty,而且基於OpenResty開源了一個Web框架Vanilla(香草),模仿了Yaf的使用習慣,讓PHP的開發更容易接受和上手。Vanilla已經在新浪移動開始使用,一些核心業務,比如高清圖和體育直播,正在向這個框架遷移中。

4.入門痛點,以及學習的正確方法

我和周晶的入門,都是自己摸著石頭過河。當時除了Python社區「大媽」的那篇使用文章外,找不到其他的資料。

奇虎和新浪都用OpenResty成功替換了之前的技術,但問題還是挺明顯,就是大家都認為自己是孤獨的使用者,同事中基本沒有人認同。在關鍵和支撐業務上,使用OpenResty有些不放心,都會在邊緣業務上先做嘗試和驗證。

雖然OpenResty的性能做的很棒,比肩或者超過其他所有的高性能解決方案,但是擔心沒有學習資料、擔心招不到人、擔心沒人交流,可能還擔心作者章亦春哪天撂挑子不幹了,這個項目就黃了。

高可用架構群里的各位都是架構師,是技術決策者,在引入一門新技術的時候,肯定會考慮到這些風險。比如小米科技馬利超在高可用架構的分享,他們在搶購系統中曾經使用過ngx_lua,雖然性能滿足需求,但是團隊裡面熟悉的人少,最後還是改成了Go語言實現。

如何解決這些擔憂?社區是有過思考和討論的,我們放在分享最後講。先從一個嘗試使用這門技術的開發者的角度看,OpenResty不少基礎工作沒有完善,友好程度不夠:

只能從源碼安裝,沒有apt-get、brew等軟體倉庫安裝方法;安裝第三方庫沒有PIP、NPM之類的包管理工具,需要去先谷歌,然後拷貝代碼文件到指定的目錄下,才能require使用。

代碼編寫需要修改nginx.conf和對應的lua代碼,即使是helloworld也是如此。當然你可以把代碼寫在nginx的配置文件裡面,但是生產環境肯定是要分離的。這種編寫代碼的方式,不像是一個編程語言,和常規的編程方式不同。

有獨特的執行階段概念,因為OpenResty是基於nginx的,所以也繼承它的這種概念。你的代碼邏輯,可能需要放在不同的階段裡面運行,才能獲取你想要的預期。而這些階段間信息如何傳遞,以及哪些API不能在某些階段使用,就會經常攔住新手。

遇到問題只有郵件列表這一種方式來溝通,而郵件列表是被牆的。文檔也只有英文版本,導致很多新手的問題無法被解決。

沒有系統學習OpenResty的手段,大都是業務需要實現什麼功能,就去文檔和API裡面去找。至於方式對不對,能不能優化,就不知道了。

㈧ android 什麼情況會用lrucache

Volley是Google在Google I/O 2013上發布的一個網路框架,主要功能:web介面請求,網路圖片非同步下載,支持緩存。volley只是定義了緩存以及Request的介面,具體實現可以自己定義,例如lru磁碟緩存,內存緩存,下載圖片的ImageRequest. Volley的源代碼里包含了一些實現,都在com.Android.volley.toolbox包里,包括磁碟緩存、json請求,圖片請求。還定義了一個繼承自ImageView的NetworkImageView,可以非同步載入網路圖片。

㈨ 用什麼替換掉bitmap.getByteCount

private LruCache<String, Bitmap> mMemoryCache;

@Override
protected void onCreate(Bundle savedInstanceState) {
// 獲取到可用內存的最大值,使用內存超出這個值會引起OutOfMemory異常。
// LruCache通過構造函數傳入緩存值,以KB為單位。
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// 使用最大可用內存值的1/8作為緩存的大小。
int cacheSize = maxMemory / 8;
mMemoryCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap bitmap) {
// 重寫此方法來衡量每張圖片的大小,默認返回圖片數量。
return bitmap.getByteCount() / 1024;
}
};
}

public void addBitmapToMemoryCache(String key, Bitmap bitmap) {
if (getBitmapFromMemCache(key) == null) {
mMemoryCache.put(key, bitmap);
}
}

public Bitmap getBitmapFromMemCache(String key) {
return mMemoryCache.get(key);
}
這裡面的bitmap.getByteCount()不行,需要API12才行,所以,我是查找了很多地方,最後看到了源碼,這個是
可以替換的,可以用bitmap.getRowBytes() * bitmap.getHeight()代替。
bitmap.getRowBytes():Since API Level 1,用於計算點陣圖每一行所佔用的內存位元組數。
bitmap.getHeight():Since API Level 1,用於計算點陣圖行數。

bitmap.getByteCount():Since API Level 12,用於計算點陣圖所佔用的內存位元組數。

熱點內容
php支付程序 發布:2024-05-03 01:07:09 瀏覽:287
安卓插口是什麼型號圖片 發布:2024-05-03 01:01:57 瀏覽:253
移動android開發 發布:2024-05-03 00:26:42 瀏覽:628
安卓上的字體怎麼放大 發布:2024-05-03 00:26:38 瀏覽:304
奧迪a3低配中配推薦哪個配置 發布:2024-05-03 00:22:12 瀏覽:242
python類聲明變數類型 發布:2024-05-03 00:22:05 瀏覽:641
碼資料庫 發布:2024-05-03 00:15:03 瀏覽:557
旗魚影視緩存教程 發布:2024-05-02 23:57:46 瀏覽:592
c語言中的階層 發布:2024-05-02 23:52:14 瀏覽:861
qt編程快速入門 發布:2024-05-02 23:41:04 瀏覽:974