Suspend to RAM和Suspend to Idle分析,以及在HiKey上效能對比
測試環境:AOSP 7.1.1+Kernel 4.4.17 HW:HiKey
Ubuntu 14.04+Kernel 4.4.0-31
1. Linux核心suspend狀態
Linux核心支援多種型別的睡眠狀態,通過設定不同的模組進入低功耗模式來達到省電功能。
目前存在四種模式:suspend to idle、power-on standby(Standby)、suspend to ram(STR)和sudpend to disk(Hibernate),分別對應ACPI狀態的S0、S1、S3和S4。
State in Linux | Label | state | ACPI state | 註釋 |
#define PM_SUSPEND_ON ((__force suspend_state_t) 0) | 一切正常 | |||
#define PM_SUSPEND_FREEZE ((__force suspend_state_t) 1) | freeze | Suspend-to-Idle | S0 | 凍結程序+掛起裝置+CPU空閒 |
#define PM_SUSPEND_STANDBY ((__force suspend_state_t) 2) | standby | Standby/Power-on Suspend | S1 | 凍結程序+掛起裝置+關閉nonbootCPU |
#define PM_SUSPEND_MEM ((__force suspend_state_t) 3) | mem | Suspend-to-RAM | S3 | 僅保留RAM自重新整理 |
#define PM_SUSPEND_MAX ((__force suspend_state_t) 4) | disk | Suspend-to-disk | S4 |
關閉所有裝置包括RAM,也被稱為Hibernate |
從freeze-->standby-->mem睡眠程度越來越深,喚醒花費的時間也越來越多。
Suspend-To-Idle
此狀態包括frozen processes+suspended devices+idle processors,具有輕量化的特點;
並且相對於相對於Idle狀態能節省更多的功耗,因為此時的使用者空間被凍結且I/O裝置進入了低功耗狀態。
相對於Suspend-To-RAM它具有低延時的優勢。
Standby/Power-On Suspend
此狀態包括frozen processes+suspended devices+offline nonboot CPUs+suspend low-level system,對CPU的處理更近一步。
所以相對於Suspend-To-Idle節省了更多的功耗,但是由於需要恢復CPU和一些底層功能也花費了更多的時間。
Suspend-to-RAM
此狀態使所有的裝置進入低功耗狀態,僅保留RAM自重新整理。
所有的裝置和系統狀態都儲存在RAM中,所有外設被掛起。
(在HiKey的實際測試中,boot CPU是沒有關閉的!實際上這裡也沒有standby,mem和standby基本上沒有區別。)
Suspend-to-disk
此狀態是最省功耗的模式。
相對Suspend-to-RAMRAM能節省更多功耗的原因是資料會被寫入磁碟中,RAM也可以被關閉。
但是這也導致了,更多的恢復延時,在resume的時候讀回到RAM,然後在進行系統和裝置狀態恢復工作。
但是在一般的嵌入式裝置上,此種狀態不支援。
下面用STR表示Suspend to RAM,STI表示Suspend to Idle。
2. Suspend狀態,以及STR 和STI區別
寫入/sys/power/state不同字串,可以讓系統進入不同睡眠狀態。
針對state sysfs節點的寫入,最終會進入到state_store這個函式,將字串轉換成上表中不同狀態。
state_store(kernel/power/main.c) -->pm_suspend (kernel/power/suspend.c)-------------處理除freeze、standby、mem三種類型suspend -->enter_state---------------------------------在進入睡眠之前,做一些準備工作 -->suspend_devices_and_enter -->suspend_enter-----------------------這裡才是freeze與standby/mem區別所在。 -->hibernate---------------------------------------進入suspend to disk流程
STR和STI的最主要區別就是下面一段程式碼:
static int suspend_enter(suspend_state_t state, bool *wakeup) { … /* * PM_SUSPEND_FREEZE equals * frozen processes + suspended devices + idle processors. * Thus we should invoke freeze_enter() soon after * all the devices are suspended. */
//====================================FREEZE=============================================================== if (state == PM_SUSPEND_FREEZE) {------------------------------------如果要進入freeze狀態,就會執行此段程式碼。 trace_suspend_resume(TPS("machine_suspend"), state, true); freeze_enter(); trace_suspend_resume(TPS("machine_suspend"), state, false); goto Platform_wake;----------------------------------------------在執行結束跳轉到Platform_wake,中間一段綠色程式碼將會被跳過。所以說freeze和standby、mem相比,多了freeze_enter,少了對non-boot CPUs、arch、syscore的操作。 } //=====================================MEM=============================================================== error = disable_nonboot_cpus(); if (error || suspend_test(TEST_CPUS)) { log_suspend_abort_reason("Disabling non-boot cpus failed"); goto Enable_cpus; } arch_suspend_disable_irqs(); BUG_ON(!irqs_disabled()); error = syscore_suspend(); if (!error) { *wakeup = pm_wakeup_pending(); if (!(suspend_test(TEST_CORE) || *wakeup)) { trace_suspend_resume(TPS("machine_suspend"), state, true); error = suspend_ops->enter(state); trace_suspend_resume(TPS("machine_suspend"), state, false); events_check_enabled = false; } else if (*wakeup) { pm_get_active_wakeup_sources(suspend_abort, MAX_SUSPEND_ABORT_LEN); log_suspend_abort_reason(suspend_abort); error = -EBUSY; } syscore_resume(); } arch_suspend_enable_irqs(); BUG_ON(irqs_disabled()); Enable_cpus: enable_nonboot_cpus(); Platform_wake: platform_resume_noirq(state); dpm_resume_noirq(PMSG_RESUME); … }
3 suspend/resume流程梳理
下面分析一下suspend/resume每個細分階段。
整個suspend可以分為若干階段,每個階段函式—>關鍵節點Trace—>analyze_suspend.py解析Trace—>根據Trace時間畫出Timeline圖表
這樣就可以分析出總的時間差異,每個階段差異,甚至一個裝置suspend/resume、一個子系統suspend/resume的時間差異。
analyze_suspend.py 基於預設基於ftrace進行分析(在指定dmesg的時候,會發現缺失了很多log資訊,無法生成timeline型別的html檔案),將suspend/resume分為若干階段。
下面簡要介紹一下各個階段,然後基於此進行程式碼分析。
在kernel版本大於等與3.15之後,解析需要的所有log資訊都可以從ftrace中獲取。之前的核心版本還需要藉助於dmesg。
由於使用的kernel版本是4.4.17,sysvals.usetraceeventsonly被置位,所以只會parseTraceLog()。
下表中的各個階段通過解析suspend_resume: XXXXXXX型別的ftrace來獲取。
各子模組、子系統的解析通過device_pm_callback_start和device_pm_callback_end來擷取時間段,以及這時間段內的callgraph。
Phase名稱 | ftrace關鍵詞 |
suspend_prepare | dpm_prepare |
suspend | dpm_suspend |
suspend_late | dpm_suspend_late |
suspend_noirq | dpm_suspend_noirq |
suspend_machine | machine_suspend start |
resume_machine | machine_suspend end |
resume_noirq | dpm_resume_noirq |
resume_early | dpm_resume_early |
resume | dpm_resume |
resume_complete | dpm_complete |
下面是一組suspend/resume執行ftrace log,我們將據此進行各階段程式碼分析,包括suspend_enter、suspend_prepare、suspend、suspend_late、suspend_noirq、suspend_machine、resume_machine、resume_noirq、resume_early、resume、resume_complete。
從這裡也可以看出freeze和mem/standby除了machine部分不同之外,還少了CPU開關和syscore suspend/resume操作。
suspend_resume: suspend_enter[1] begin |
suspend_resume: suspend_enter[3] begin |
在介紹相關程式碼之前,先介紹一下HiKey使用的platform_suspend_ops:
static const struct platform_suspend_ops psci_suspend_ops = { |
freeze的platform_freeze_ops如下:
static const struct platform_freeze_ops acpi_freeze_ops = { |
3.1 suspend_enter
enter_state作為suspend/resume的入口點,完成了絕大部分工作。首先確保系統沒有正在進入睡眠狀態;然後為suspend做一些準備,使系統進入睡眠並在喚醒後進行必要清理恢復工作。
下面分析一下suspend之前的準備工作,即suspend_enter階段:
static int enter_state(suspend_state_t state) { int error; trace_suspend_resume(TPS("suspend_enter"), state, true); if (state == PM_SUSPEND_FREEZE) {--------------------------------------是否是freeze型別suspend #ifdef CONFIG_PM_DEBUG if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) { pr_warning("PM: Unsupported test mode for suspend to idle," "please choose none/freezer/devices/platform.\n"); return -EAGAIN; } #endif } else if (!valid_state(state)) {-------------------------------------目前只支援mem型別suspend return -EINVAL; } if (!mutex_trylock(&pm_mutex)) return -EBUSY; if (state == PM_SUSPEND_FREEZE) freeze_begin();--------------------------------------------------初始化suspend_freeze_state為FREEZE_STATE_NONE #ifndef CONFIG_SUSPEND_SKIP_SYNC trace_suspend_resume(TPS("sync_filesystems"), 0, true); printk(KERN_INFO "PM: Syncing filesystems ... "); sys_sync();----------------------------------------------------------sync檔案系統快取檔案,確保資料sync到硬碟。 printk("done.\n"); trace_suspend_resume(TPS("sync_filesystems"), 0, false); #endif pr_debug("PM: Preparing system for sleep (%s)\n", pm_states[state]); pm_suspend_clear_flags(); error = suspend_prepare(state);--------------------------------------注意這裡面的suspend_prepare和下面的suspend_prepare階段容易搞混。 if (error) goto Unlock; if (suspend_test(TEST_FREEZER)) goto Finish; trace_suspend_resume(TPS("suspend_enter"), state, false); pr_debug("PM: Suspending system (%s)\n", pm_states[state]); pm_restrict_gfp_mask(); error = suspend_devices_and_enter(state); pm_restore_gfp_mask(); Finish: pr_debug("PM: Finishing wakeup.\n"); suspend_finish();---------------------------------------------------解凍,重啟程序;傳送PM_POST_SUSPEND通知;釋放之前分配的console。 Unlock: mutex_unlock(&pm_mutex); return error; }
接著分析一下suspend_prepare函式:
static int suspend_prepare(suspend_state_t state) if (!sleep_state_supported(state)) 驗證suspend狀態 pm_prepare_console(); 分配一個suspend console error = pm_notifier_call_chain(PM_SUSPEND_PREPARE); 傳送PM_SUSPEND_PREPARE通知訊息 trace_suspend_resume(TPS("freeze_processes"), 0, true); suspend_stats.failed_freeze++; |
suspend_freeze_process先處理使用者空間程序,然後處理核心程序:
static inline int suspend_freeze_processes(void) error = freeze_processes(); 觸發使用者空間程序進入freeze狀態。當前程序不會被凍結。因為凍結失敗的程序會自動被解凍,所以不需要進行錯誤處理。 error = freeze_kernel_threads(); 凍結核心執行緒 return error; |
下面的階段都在suspend_devices_and_enter中,可以看出這是一個對稱的流程,每一階段的suspend,都有對應的resume。
int suspend_devices_and_enter(suspend_state_t state) if (!sleep_state_supported(state)) error = platform_suspend_begin(state); suspend_console(); 關閉console子系統,暫停printk列印 do { Resume_devices: Close: Recover_platform: |
還有必要過一下suspend_enter:
static int suspend_enter(suspend_state_t state, bool *wakeup) error = platform_suspend_prepare(state); 因為suspend_ops的prepare為空,所以返回0 error = dpm_suspend_late(PMSG_SUSPEND); suspend_late error = dpm_suspend_noirq(PMSG_SUSPEND); suspend_noirq if (suspend_test(TEST_PLATFORM)) /* error = disable_nonboot_cpus(); 關閉所有boot-CPU之外的CPU arch_suspend_disable_irqs(); error = syscore_suspend(); 執行syscore_ops_list上所有syscore_ops的suspend回撥函式 arch_suspend_enable_irqs(); Enable_cpus: Platform_wake: Platform_early_resume: Devices_early_resume: Platform_finish: |
3.2 suspend_prepare和suspend
DPM是Device Power Management的意思,這些操作都是針對非系統裝置(non-sysdev)進行的。那什麼是系統裝置呢?下面的machine應該就是所謂的sysdev了。
dpm_prepare實際上就是遍歷dpm_list上的所有裝置,執行->prepare回撥函式。如果裝置存在->prepare回電函式,會將裝置的prepare階段列印到ftrace。
int dpm_prepare(pm_message_t state) trace_suspend_resume(TPS("dpm_prepare"), state.event, true); mutex_lock(&dpm_list_mtx); get_device(dev); trace_device_pm_callback_start(dev, "", state.event); mutex_lock(&dpm_list_mtx); |
dpm_suspend遍歷dpm_prepared_list,這點和dpm_prepare有區別。然後執行裝置的->suspend回撥函式。
int dpm_suspend(pm_message_t state) trace_suspend_resume(TPS("dpm_suspend"), state.event, true); cpufreq_suspend(); mutex_lock(&dpm_list_mtx); get_device(dev); error = device_suspend(dev); 執行裝置->suspend回撥函式 mutex_lock(&dpm_list_mtx); |
3.3 suspend_late和suspend_noirq
dpm_suspend_late基於dpm_suspended_list操作裝置,所以這也需要函式之間順序執行。
int dpm_suspend_late(pm_message_t state) trace_suspend_resume(TPS("dpm_suspend_late"), state.event, true); while (!list_empty(&dpm_suspended_list)) { 遍歷dpm_suspended_list列表 get_device(dev); error = device_suspend_late(dev); 執行->suspend_late回撥函式 mutex_lock(&dpm_list_mtx); if (error) { if (async_error) |
dpm_suspend_noirq基於dpm_late_early_list遍歷所有裝置。首先阻止裝置驅動接收中斷資訊,然後執行->suspend_noirq回撥函式。
int dpm_suspend_noirq(pm_message_t state) trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, true); while (!list_empty(&dpm_late_early_list)) { get_device(dev); error = device_suspend_noirq(dev); 呼叫->suspend_noirq回撥函式 mutex_lock(&dpm_list_mtx); if (async_error) if (error) { |
3.4 suspend_machine和resume_machine
freeze和mem/standby在這部分是不同的。
mem/standby直接呼叫suspend_ops->enter進入對應的睡眠模式。
而freeze就要稍微複雜了:
static void freeze_enter(void) suspend_freeze_state = FREEZE_STATE_ENTER; get_online_cpus(); /* Push all the CPUs into the idle loop. */ spin_lock_irq(&suspend_freeze_lock); out: |
3.5 resume_noirq
執行dpm_noirq_list上裝置的resume_noirq回撥函式。
void dpm_resume_noirq(pm_message_t state) trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, true); /* while (!list_empty(&dpm_noirq_list)) { 遍歷dpm_noirq_list if (!is_async(dev)) { error = device_resume_noirq(dev, state, false); mutex_lock(&dpm_list_mtx); |
3.6 resume_early
執行前述dpm_late_early_list裝置的resume_early回撥函式,移動裝置到dpm_suspended_list列表。
void dpm_resume_early(pm_message_t state) trace_suspend_resume(TPS("dpm_resume_early"), state.event, true); /* while (!list_empty(&dpm_late_early_list)) { if (!is_async(dev)) { error = device_resume_early(dev, state, false); |
3.7 resume
執行所有dpm_suspended_list上裝置的resume回撥函式。
void dpm_resume(pm_message_t state) trace_suspend_resume(TPS("dpm_resume"), state.event, true); mutex_lock(&dpm_list_mtx); list_for_each_entry(dev, &dpm_suspended_list, power.entry) { while (!list_empty(&dpm_suspended_list)) { mutex_unlock(&dpm_list_mtx); error = device_resume(dev, state, false); mutex_lock(&dpm_list_mtx); cpufreq_resume(); |
3.8 resume_complete
執行所有dpm_prepared_list上裝置的complete回撥函式。至此dpm_complete結束所有非系統裝置的睡眠。
void dpm_complete(pm_message_t state) trace_suspend_resume(TPS("dpm_complete"), state.event, true); INIT_LIST_HEAD(&list); get_device(dev); trace_device_pm_callback_start(dev, "", state.event); mutex_lock(&dpm_list_mtx); |
4 如何讓HiKey進入STR/STI並喚醒?
可以通過配置GPIO作為喚醒源,或者通過RTC作為喚醒源,延時一定時間來喚醒。
檢查是否存在/sys/class/rtc/rtc0/wakealarm,入不存在則需要開啟CONFIG_RTC_DRV_PL031。
寫入wakealarm的引數,表示在多少秒之後resume喚醒,退出suspend。
寫mem進入state,是系統進入suspend流程。
adb root && adb remount adb shell "echo +10 > /sys/class/rtc/rtc0/wakealarm && echo mem > /sys/power/state" |
5. suspend/resume的latency分析手段
5.1 analyze_suspend.py v3.0
在kernel的scripts中,這個工具可以幫助核心和OS開發者優化suspend/resume時間。
在開啟一系列核心選項之後,此工具就可以執行suspend操作,然後抓取dmesg和ftrace資料知道resume結束。
這些資料會按照時間線顯示每個裝置,並且顯示佔用最多suspend/resume時間的裝置或者子系統的呼叫關係詳圖。
執行工具後,會根據時間生成一個子目錄,裡面包含:html、dmesg和原始ftrace檔案。
下面簡單看一下工具選項:
Options: |
在瞭解了工具使用方法之後,就可以進行相關測試了。
5.1.1 Android
./analysze_suspend.py –modes –adb /usr/bin/adb獲取當前系統支援的suspend狀態。
['freeze', 'mem'] |
1.Android上測試STR,suspend/resume共5次,每次間隔20秒。
./analyze_suspend.py -adb /usr/bin/adb -rtcwake 10 -multi 5 20 -f -m mem |
2.Android上測試STI,suspend/resume共10次,每次間隔5秒。
./analyze_suspend.py -adb /usr/bin/adb -rtcwake 10 -multi 5 20 -f -m freeze |
測試結果可以在如下獲得:
存在的問題:analyze_suspend.py不支援Android的rtcwakeup和callgraph。已經在如下fix:
5.1.1.1 總體對比
下面是HiKey上測試結果,可以看出兩個資料都不夠穩定。mem的suspend和resume平均值都比較高。
freeze相比mem的suspend/resume平均值提高了304.3ms/613.5ms。
5.1.1.2 是否suspend CPU
對比如下兩幅圖,明顯看出mem型別的suspend關閉了除CPU0之外的所有CPU;而freeze則沒有關閉任何CPU。
non-boot CPUs的suspend/resume時間就達到300ms/200ms。
同時從log中也可以看出mem和freeze的主要區別就在於是否disabling/enabling non-boot CPU。其他裝置和子系統的suspend/resume時間基本一致。
同時還可以看出mem的suspend後,系統的timestamp是停止的;而freeze的timestamp還是一直在執行的。可以得出freeze狀態持續的時間。
因為先寫rtcwake為10s,然後進入睡眠,再喚醒,所以freeze時間是小於10s的。
[ 3385.642962] PM: suspend entry 1970-01-01 00:57:30.580909763 UTC |
|
5.1.1.3 resume_console節省時間
對比resume_console可以發現,mem要比freeze多210ms。
5.1.2 Ubuntu
此工具在Ubuntu上顯示了更強大的功能。
支援了callgraph功能之後,更能清晰地分析每個裝置或者子系統的suspend/resume佔用的時間。
sudo ./analyze_suspend.py -rtcwake 10 -multi 5 20 -f -m mem sudo ./analyze_suspend.py -rtcwake 10 -multi 5 20 -f -m freeze |
在對比兩種不同suspend模式後,發現freeze花費的時間要比mem少。這也符合預期,但是沒有功耗資料?_?。
測試環境:AOSP 7.1.1+Kernel 4.4.17 HW:HiKey
Ubuntu 14.04+Kernel 4.4.0-31
1. Linux核心suspend狀態
Linux核心支援多種型別的睡眠狀態,通過設定不同的模組進入低功耗模式來達到省電功能。
目前存在四種模式:
one-to-many(一對多)和many-to-one(多對一)雙向關聯
假設部門與員工是一對多關係,反過來員工與部門就是多對一關係。
Dept.java類
public class Dept implements java.io.Serializable {
一、前言
在前幾天中自己在學習ssh的過程中,發現Hibernate需要配置一個名字叫xxx.hbm.xml的檔案,這個檔案主要是使用Hibernate對映到相應的表。自然在這個檔案裡面會
SpringDataJPA是Spring Data的一個子專案,通過提供基於JPA的Repository極大的減少了JPA作為資料訪問方案的程式碼量,你僅僅需要編寫一個介面整合下SpringDat
一對多,主要從兩個實體出發,看強調的重點是一還是多的一端,也就是外來鍵所在的一端,如果外來鍵所在一端是一那麼對關係的維護就需要在一的一端。
如果外來鍵在多的一端那麼這個時候就應該是“多對一”維護端需要建立在多的一端。
如果兩端都有互相的主鍵作為外來鍵,那麼這個
一段C語言和彙編的對應分析,揭示函式呼叫的本質
2018年09月30日 13:32:19 sdulibh 閱讀數:17
本文作者周平,原創作品轉載請註明出處
首先對會涉及到的一些CPU暫存器和彙編的基礎知識羅列一下:
16位、32位、64
你始終記住 * 就是取值的,
例:*p,你看看p中存的是什麼是地址的話就是去這個地址中存的內容,如不是抵制就返回0;
程式碼如下:
string ww="zhj";
string * dizhi=&ww;//存的地址
cout <&
在第一篇部落格中 我們初步瞭解了jni程式設計的步驟,那接下來我認為極其重要的事情是搞清楚jni.h標頭檔案裡面的結構,包括資料型別和方法的定義等,這些是必須的,否則沒有辦法進行學習,就像寫文章一樣,要先學會寫字是一樣的道理。
首先來看一下jni.h標頭檔案的組成:ps下面 前言
現如今市場上的人事系統五花八門,可做了大資料分析的人事系統少之又少,最近本人花了一個星期好好研究了大資料展示方面的內容,圖表主要用的是echarts來實現的,官網地址:https://echarts.apache.org/zh/index.html
下面兩張圖片 ans toc contain exp red lec adb service 接口 轉:http://blog.csdn.net/xinghun_4/article/details/50492041
容器網絡實例
服務中的3個端口設置
這幾個port的概念很容易混淆,比 出錯 同時 分享圖片 spl 們的 是什麽 cti 接下來 版本 參考資料
http://www.laruence.com/2015/05/28/3038.html
http://php.net/manual/zh/class.generator.php
htt compareto map.entry 排序 區別 sta hashmap 得到 package log 獲取map的值主要有四種方法,這四種方法又分為兩類,一類是調用map.keySet()方法來獲取key和value的值,另一類則是通過map.entrySet()方法來
①**.js和**.min.js的區別 引用 Q: .js和.min.js檔案分別是什麼? A: .js是JavaScript 原始碼檔案, .min.js是壓縮版的js檔案。
Q:為什麼要壓縮為.min.js檔案?
減小體積 .min.js檔案經過壓縮,相對編譯前的js檔案體積較小
過擬合:
過擬合(over-fitting)是所建的機器學習模型或者是深度學習模型在訓練樣本中表現得過於優越,導致在驗證資料集以及測試資料集中表現不佳的現象。就像上圖中右邊的情況。 過擬合的模型太過具體從而缺少泛化能力,過度的擬合了訓練集中的資料。出現的原因是模型將其中的不重要的變 json作用:
將python的資料型別轉化為字串,便於在網路或者各種程式語言中傳遞。
方法:dumps(),loads()
把python的資料直接放入括號內第一位引數即可,返回序列化之後的json字串,
- json字串就是一種字串,
- 字串很容易儲存和傳遞
- json字串可以
什麼是執行緒?
Linux下執行緒用程序PCB模擬描述,也叫輕量級程序
執行緒是程序內部的一個執行流,也就是執行緒在程序的地址空間內執行。
一個程序內的所有執行緒共享程序資源
執行緒是CPU排程的基本單位(CPU排程是按照PCB進行排程的)
建立,銷燬一個執行緒相較
我們可以先通過輸入netstat -an|grep,來檢視一下當前的總埠。
&nb
這兩年Rxjava火的一塌糊塗,不會點Rxjava+Okhttp+Retrofit+MVP+Dagger2架構都不好意思說自己混Android的。Rxjava 到底是什麼和Rxjava到底怎麼用,這裡就不講了,網上太多了,具體可以參考 這位大佬 和扔物線的。
Rxjava
一、redis的安裝先在下載安裝包解壓後進入目錄應為已經有Makefile了所以直接make編譯這裡會報錯,需要gcc編譯器安裝好gcc,再次make編譯,還是會報錯;這個錯誤根據 Readme 可知需要執行 make MALLOC=libcmake完成後,提示去到 src
JJMETER 3.1可以和最新版本的badboy匹配以及和最新版本的JMETER外掛匹配;連結:https://pan.baidu.com/s/1ah_5ewIKE-4X4XzwR0TcFA 密碼:getb 永久有效 雖然Jmeter功能相對完善,但基本可以滿 相關推薦
Suspend to RAM和Suspend to Idle分析,以及在HiKey上效能對比
JPA關係對映之one-to-many和many-to-one(另inverse=“true”解析)
【java】xxx.hbm.xml檔案中的many-to-one和one-to-many理解
JPA關係對映系列三:one-to-many和many-to-one
關於Hibernate中many-to-one和one-to-many的一些理解
一段C語言和彙編的對應分析,揭示函式呼叫的本質
字元指標和整形指標簡單分析,*,&的作用。
Jni程式設計(二)jni.h 標頭檔案定義分析,以及c/c++呼叫java類的屬性和方法
怎麼實現員工和工資大資料分析,echarts+js實現
kubernetes中port、target port、node port的對比分析,以及kube-proxy代理
PHP yield 分析,以及協程的實現,超詳細版(上)
Map四種獲取key和value值的方法,以及對map中的元素排序(轉)
JS檔案的**.js和**.min.js的區別,以及js函式執行的順序
機器學習中的過擬合和欠擬合現象,以及通過正則化的方式解決。
json,dump()和dump()區別,以及如何序列化一個物件
程序和執行緒的區別,以及應用場景
關於ftp和ssh修改埠之後,連線不上的問題
Rxjava2.x 原始碼分析,以及手動實現Rxjava(一)
redis的主從複製和高可用、叢集,以及用redis做mysql快取
JMETER 3.1版本和 JMETER-Plugins 外掛資源,以及各個外掛的用法