2010年12月29日星期三

Visual Studio 插件推介–metalscroll

早前我曾經介紹過 RockScroll 這個插件,如今我找到了一個更好的代替品 metalscroll

它比起 RockScroll 有很多細節的改善,最重要是掛掉的情況沒有了。

2010年2月24日星期三

讓工作管理員進行繪圖

興之所致,找來一個有趣面試題目來解答:如何能讓CPU 的使用率表現為一條正弦曲線?

這個題目來自《编程之美--微软技术面试心得》,有機會的我會話買下來當作娛樂。

// This program try to burn cpu cycles with a sinusoid function against the time.
#include <MCD/Core/System/TaskPool.h>
#include <MCD/Core/System/Timer.h>
#include <math.h>

class Task : public MCD::TaskPool::Task {
public:
Task(float frequency) : MCD::TaskPool::Task(0), mFrequency(frequency) {}

sal_override void run(MCD::Thread& thread) throw() {
MCD::Timer timer;
while(thread.keepRun()) {
double current = timer.get().asSecond();
double busy = (sin(current * mFrequency) + 1) / 2;
double idle = 1 - busy; // We base on a 1 second interval
while(timer.get().asSecond() < current + busy) {} // Burn CPU cycles
MCD::mSleep(int(idle * 1000)); // Let CPU idle
}

// The Task instance is not needed any more, destroy it.
delete this;
}

float mFrequency;
}; // Task

int main(int, char const*[])
{
const size_t cpuCount = 4; // Set this to match your hardware thread count
const float frequency = 0.1f;

MCD::TaskPool taskPool;
taskPool.setThreadCount(cpuCount);

for(size_t i=0; i<cpuCount; ++i)
taskPool.enqueue(*new Task(frequency));

std::cout << "Press enter to quit...\n";
std::cin.get();

taskPool.stop();

return 0;
}

sinusoidTaskManager

註:中間的那個高峰因突如其來的 MSN 短訊耗掉了整整一個 CPU Core 而缺了一角。

2009年12月15日星期二

Virtual box shared folders 備忘

Virtual box 3.1 已支援 OpenGl 2.1,MCore 的 Linux port 也可繼續。

已往我使用 smbfs 來 mount Windows 的網絡磁碟機:

//192.168.0.1/mcore3d /home/ricky/mcore3d smbfs iocharset=utf8,unicode,username=xxx,password=xxx 0 0

不過很容易會有權限或 encoding 的問題,而某個 library 更新之後又會有機會使原有設定失效。

比較之下,Virtual box 提供的 shared folders 就可靠得多:

mcore3d /home/ricky/mcore3d vboxsf defaults 0 0

2009年12月2日星期三

為灰鼠捉蟲

使用了 Squirrel 已好一些日子,終於給我遇到了臭蟲。這臭蟲的表徵是不確定的行為,debug/release/,run-with/without debugger 都會產生不同的結果。這一類不確定的行為不是多緒就是錯誤記憶體存取做成,而面對著陌生的 code base,最好的捉蟲方法就是使用專門的工具,如 Intel Parallel Studio 提供的 Parallel Inspector

最終找到錯誤源於一處被 reference 的記憶體給 realloc 了;餘下的就交給 Squirrel 作者處理

Invalid memory access

2009年10月21日星期三

Squirrel remote debugger

以下是完成了大約三分之一的 Squirrel 遠程除錯器。當中的製作過程比想像中簡單,皆因 Squirrel 已有一個除錯伺服器的實作 sqdbg,而我需要做的只是客戶端與 Gui。

Sqdbg 的編程界面僅有四個函數,使用 Xml 來進行客戶端溝通。如今加減中斷點,下一行,跳出跳入和暫停繼續等等已經完成,接下來還有堆疊,變量監視等工夫。

除了結合自家的遊戲引擎,它也會獨立出來貢獻給 Squirrel 社群。

SqdbgClient

2009年9月17日星期四

In-Game C++ Memory Profiler

忙碌了兩個多月,這篇有可出現在 Gems 系列的 "In-Game Memory Profiler" 終於完成。製作這類 Profiler 已經不知多少次了,但這次是最滿意的;可以媲美需付款的產品 (其實類似的 C++ memory profiler 產品真的少之又少),甚至更好。就是它,讓我知道 Bullet 每次 step simulation 都有好幾千個即用即棄的 memory allocation/de-allocation;後來我把它的 default pool size 增大,問題也就解決了。

In-Game-Memory-Profiler

2009年9月5日星期六

弱指針的重要性

雖然有許多有關智能指針 (Smart pointer) 的文章和範例,但關於弱指針的就相對寥寥無幾。縱然有所提及,也只是草草幾筆說弱指針是用來避免 "循環引用 (Cyclic reference)" 云云。就此問題我嘗試用一些例子去補充說明弱指針何時用,為什麼用。

首先讓我們看一個遊戲引擎中典型的資料管理系統例子:

因為要節省內存的需求,Texture (紋理) 被設計成能夠給多個 Model (三維模型) 共享。而 Texture 的存在目的,就是留給 Model 作為繪畫時使用;明顯地,Model 可用 Smart Pointer 來引用 Texture;相對地 NameToTextureMap (方便用名稱來作資料搜尋) 該使用甚麼來引用 Texture 就沒有那麼明顯了。先看看使用不同的指針會有什麼的後果吧。
  • 裸指針 - 這將會是災難性的選擇,因為一旦再沒有 Model 引用 Texture, NameToTextureMap 就會在毫無知會的情況下指向一件非法的物件。

  • 智能指針 - 為了解決裸指針的問題,選擇智能指針像是合理的做法。不過請大家想一想,一旦 NameToTextureMap 引用了 Texture 以後,何時才可刪除引用呢?假如不去刪除引用,Texture 的生命期就會與 NameToTextureMap 同步化,失去了原先使用智能指針作為純粹被 Model 共享的意義。
這時就是讓弱指針發揮的時候。弱指針的特性就是當它指向的物件被銷毀之時,弱指針的值就會瞬間變為零;因此,讓 NameToTextureMap 使用弱指針,再定期把零值的弱指針由容器中刪除,以上的 UML 設計就可忠實地實作出來。

總結來說,智能指針旨不在於提供程序員不加思索就可使用的工具,它是一種能幫助你正確地實行擁有權共享的工具。就算是聲稱擁有自動內存管理的語言如 Java, C#, Python, Ruby 等等都一定會有弱指針這個概念,否則內存洩漏是很難避免的。假若你在開發 C++ 程序的時候遇到許多關於物件擁有權的問題,請記得弱指針的存在。