【WALT】update_task_demand() 代碼詳解

来源:https://www.cnblogs.com/cyrusandy/archive/2023/07/05/17529893.html
-Advertisement-
Play Games

# lvm邏輯捲 ## 前言 > raid磁碟陣列技術,提高硬碟的讀寫效率,以及數據的安全,raid的缺點在於: > 1.當你配置好了raid磁碟陣列組,容量的大小,已經是限定了,如果你存儲的業務非常多,磁碟容量不夠用的問題就會出現,你想要擴容磁碟的空間,就會非常麻煩。 > 2.不同的磁碟分區,相對 ...


目錄

【WALT】update_task_demand() 代碼詳解

代碼版本:Linux4.9 android-msm-crosshatch-4.9-android12

代碼展示

static u64 update_task_demand(struct task_struct *p, struct rq *rq,
			       int event, u64 wallclock)
{
	u64 mark_start = p->ravg.mark_start;
	u64 delta, window_start = rq->window_start;
	int new_window, nr_full_windows;
	u32 window_size = sched_ravg_window;
	u64 runtime;

	// 用於判斷是否進入新視窗的標誌位
	new_window = mark_start < window_start;
	// ⑴ 不累加任務運行時間的條件判斷
	if (!account_busy_for_task_demand(rq, p, event)) {
		if (new_window)
			update_history(rq, p, p->ravg.sum, 1, event);
		return 0;
	}
	
	// ⑵ 仍在舊視窗中
	if (!new_window) {
		return add_to_task_demand(rq, p, wallclock - mark_start);
	}

	// ⑶ 進入新視窗
	delta = window_start - mark_start;
	nr_full_windows = div64_u64(delta, window_size);
	window_start -= (u64)nr_full_windows * (u64)window_size;
	
	runtime = add_to_task_demand(rq, p, window_start - mark_start);

	update_history(rq, p, p->ravg.sum, 1, event);
	if (nr_full_windows) {
		u64 scaled_window = scale_exec_time(window_size, rq);

		update_history(rq, p, scaled_window, nr_full_windows, event);
		runtime += nr_full_windows * scaled_window;
	}

	window_start += (u64)nr_full_windows * (u64)window_size;
	
	mark_start = window_start;
	runtime += add_to_task_demand(rq, p, wallclock - mark_start);
	
	// ⑷ 返回值 runtime
	return runtime;
}

代碼邏輯

用於判斷是否進入新視窗的標誌位

WALT 演算法中,引入了一個新的概念:視窗(sched_ravg_window)

先介紹幾個名詞:

  • ws:window_start,當前視窗的開始時間
  • ms:mark_start,當前任務的開始時間
  • wc:wallclock,進入 WALT 演算法的時間
  • nr_full_windows,如果進入新視窗,則代表舊視窗到當前視窗所經歷的完整的視窗個數
  • delta:從任務開始到當前時間/新視窗開始時間所經歷的時長

視窗分三種情況進行劃分:

  1. 仍在舊視窗中
                    ws   ms  wc
                    |    |   |
                    V    V   V
    |---------------|===============|
    即進入 WALT 演算法到時間還在 window_start 到 window_start + sched_ravg_window 之間
    這種情況下,delta = wc - ms,只需要累加進任務時間,不需要更新
    
  2. 剛離開舊視窗,進入下一個視窗
               ms   ws   wc
               |    |    |
               V    V    V
    |---------------|===============|
    即進入 WALT 演算法到時間超過了 window_start + sched_ravg_window
    但還沒超過 window_start + sched_ravg_window * 2
    這種情況下,delta 分為兩塊,一塊是 ws - ms,一塊是 wc - ws
    兩塊都需要累加進任務時間,但 ws - ms 塊需要進行更新,因為它在舊視窗中
    
  3. 經過了數個視窗後抵達新視窗
               ms   ws_tmp                    ws   wc
               |    |                         |    |
               V    V                         V    V
    |---------------|----------|...|----------|===============|
                    |                         |
                    |<--- nr_full_windows --->|
    即進入 WALT 演算法到時間超過了 window_start + sched_ravg_window * 2
    其中經過了 nr_full_windows 個完整視窗
    這種情況下,delta 分為三塊,一塊是 ws_tmp - ms,一塊是 wc - ws,
    一塊是 sched_ravg_window * nr_full_windows
    三塊都需要累加進任務時間,但只有 wc - ws 塊不需要進行更新,因為它在新視窗中
    

通過 new_window = mark_start < window_start; 來判斷是否處在 2、3 種情況之中,如果 new_window == 1,則處在 2、3 種情況之中,否則處於第 1 種情況。

⑴ 不累加任務運行時間的條件判斷

static int 
account_busy_for_task_demand(struct rq *rq, struct task_struct *p, int event)
{
	if (exiting_task(p) || is_idle_task(p))
		return 0;
		
	if (event == TASK_WAKE || (!SCHED_ACCOUNT_WAIT_TIME &&
			 (event == PICK_NEXT_TASK || event == TASK_MIGRATE)))
		return 0;

	if (event == TASK_UPDATE) {
		if (rq->curr == p)
			return 1;
		return p->on_rq ? SCHED_ACCOUNT_WAIT_TIME : 0;
	}

	return 1;
}

在函數 account_busy_for_task_demand() 中會判斷任務經過的時間是否是 runnable 或 running 時間,返回 1 則是,返回 0 則不是。

  1. 任務經過的時間是 runnable 或 running,即返回 1 的情況
    在當前版本內核中,SCHED_ACCOUNT_WAIT_TIME 預設為 1
    • 任務更新且任務在就緒隊列中,無論是不是當前任務
    • 其他情況
  2. 任務經過的時間不是 runnable 或 running,即返回 0 的情況
    • 任務正在退出
    • 任務是 idle 任務
    • 任務剛被喚醒
    • 任務更新切任務不在就緒隊列中

如果任務經過的時間不是 runnable 或 running 時間,且正好進入新視窗,就不累加任務時間,直接通過 update_history() 將上一個視窗中已經累加的時間更新至任務結構體中(task_struct)。
點擊此處查看 update_history() 代碼詳解。

⑵ 仍在舊視窗中

根據開頭的分析,我們知道這種情況下不需要通過 update_history() 更新時間,只需要通過 add_to_task_demand() 累加任務時間。

static u64 add_to_task_demand(struct rq *rq, struct task_struct *p, u64 delta)
{
	// 1. 將 delta 時間進行歸一化
	delta = scale_exec_time(delta, rq);
	// 2. 累加進 p->ravg.sum 中
	p->ravg.sum += delta;
	if (unlikely(p->ravg.sum > sched_ravg_window))
		p->ravg.sum = sched_ravg_window;

	return delta;
}

將歸一化後的任務時間累加進 p->ravg.sum 中,在之後的 update_history() 中會將 p->ravg.sum 放進 p->ravg.sum_history 結構體中。

其中,任務時間的歸一化是 WALT 演算法中的重要部分。點擊此處查看 scale_exec_time() 代碼詳解。

⑶ 進入新視窗

根據開頭的分析,我們知道進入新視窗分為兩種情況,無論是哪種情況,都需要累加 ws_tmp - ms 和 wc - ws 兩部分。其中,如果剛離開舊視窗進入下一個視窗,則 ws = ws_tmp。

我們先處理 ws_tmp - ms 部分:

  • 先通過 delta = window_start - mark_start; 計算總體經過的時間;
  • 再通過 nr_full_windows = div64_u64(delta, window_size); 計算經過的完整視窗的數量;
  • 最後得到 ws_tmp:window_start -= (u64)nr_full_windows * (u64)window_size;
  • 累加 ws_tmp - ms 部分時間:runtime = add_to_task_demand(rq, p, window_start - mark_start);
  • 更新 ws_tmp - ms 部分時間:update_history(rq, p, p->ravg.sum, 1, event);

然後針對經過多個完整視窗情況進行時間更新。此處不需要通過 add_to_task_demand() 累加任務時間,因為任務在這些完整視窗中的時間都是從視窗開始到視窗結束。

  • 先對視窗時間進行歸一化:scaled_window = scale_exec_time(window_size, rq);
  • 更新時間:update_history(rq, p, scaled_window, nr_full_windows, event);

最後處理 wc - ws 部分。

  • 把 ws 時間還原:window_start += (u64)nr_full_windows * (u64)window_size;
  • mark_start = window_start; 此處不是更新任務的開始時間,任務開始時間在 WALT 演算法的 done 部分進行更新。如果任務開始時間在此處更新,會影響到 update_cpu_busy_time() 中的計算。
  • 累加 wc - ws 部分時間:runtime += add_to_task_demand(rq, p, wallclock - mark_start);

⑷ 返回值 runtime

最後的返回值 runtime 在該版本內核中並未使用到,它是此次執行 update_task_demand() 時一共累加的任務 runnable 和 running 時間,也就是上一次 WALT 演算法開始到這一次 WALT 演算法開始過程中,該任務的 runnable 和 running 時間。

點擊此處回到 WALT 入口函數 update_task_ravg()


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ## 教程簡介 DAX代表 Data Analysis Expressions. DAX是一種公式語言,是函數,運算符和常量的集合,可以在公式或表達式中用於計算和返回一個或多個值. DAX是與Excel Power Pivot的數據模型相關聯的公式語言. 它不是一種編程語言,而是一種允許用戶在計算列 ...
  • 學習記錄,不喜勿噴 什麼是OkHttp 一般在Java平臺上,我們會使用Apache HttpClient作為Http客戶端,用於發送 HTTP 請求,並對響應進行處理。比如可以使用http客戶端與第三方服務(如SSO服務)進行集成,當然還可以爬取網上的數據等。OKHttp與HttpClient類似 ...
  • > 作者:小牛呼嚕嚕 | [https://xiaoniuhululu.com](https://xiaoniuhululu.com/) > 電腦內功、源碼解析、科技故事、項目實戰、面試八股等更多硬核文章,首發於公眾號「[小牛呼嚕嚕](https://www.xiaoniuhululu.com/i ...
  • BeanDefinition在Spring初始化階段保存Bean的元數據信息,包括Class名稱、Scope、構造方法參數、屬性值等信息,本文將介紹一下BeanDefinition介面、重要的實現類,以及在Spring中的使用示例。 # BeanDefinition介面 用於描述了一個Bean實例, ...
  • 遠程調用百度AI開放平臺的web服務,快速完成人臉識別 ### 歡迎訪問我的GitHub > 這裡分類和彙總了欣宸的全部原創(含配套源碼):[https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) ### ...
  • 個人認為百度地圖開放平臺確實很好用但就是C#的SN校驗會出現以下幾個問題 一、官方的示例代碼說的不清不楚 獲取SN函數的Uri應該使用不帶功能變數名稱的Uri 比如:最終請求地址為https://api.map.baidu.com/location/ip?ip=119.126.10.15&coor=gcj0 ...
  • ## 一:背景 ### 1. 講故事 前段時間有位朋友找到我,說他們的工業視覺軟體僵死了,讓我幫忙看下到底是什麼情況,哈哈,其實卡死的問題相對好定位,無非就是看主線程棧嘛,然後就是具體問題具體分析,當然難度大小就看運氣了。 前幾天看一篇文章說現在的 .NET程式員 不需要學習**WinDbg** , ...
  • 記憶體“泄露”是開發中常見的問題之一,它會導致應用程式占用越來越多的記憶體資源,最終可能導致系統性能下降甚至崩潰。軟體開發者需要瞭解在程式中出現記憶體泄露的情況,以避免軟體出現該的問題。 **什麼是記憶體“泄露”?** 記憶體泄露是申請了記憶體空間的變數一直在占用,無法釋放。比如申請了一塊記憶體空間,沒有回收一直 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...