靈修分享:亞略巴古的演講

亞略巴古的演說是使徒行傳一篇非常著名的講道。基督徒往往用這段經文來說明上帝的屬性,同時也會參考這段經文作為和外邦人互動的一個參考方式。最近因為團契查經查到這一段,重新思想後看到了以前沒有考慮過的面向,在這邊記錄一下。

徒17:16-34保羅在雅典等候他們的時候,看見滿城都是偶像,就心裏着急;於是在會堂裏與猶太人和虔敬的人,並每日在市上所遇見的人,辯論。還有伊壁鳩魯和斯多亞兩門的學士,與他爭論。有的說:「這胡言亂語的要說甚麼?」有的說:「他似乎是傳說外邦鬼神的。」這話是因保羅傳講耶穌與復活的道。他們就把他帶到亞略‧巴古,說:「你所講的這新道,我們也可以知道嗎?因為你有些奇怪的事傳到我們耳中,我們願意知道這些事是甚麼意思。」(雅典人和住在那裏的客人都不顧別的事,只將新聞說說聽聽。)
保羅站在亞略‧巴古當中,說:「眾位雅典人哪,我看你們凡事很敬畏鬼神。我遊行的時候,觀看你們所敬拜的,遇見一座壇,上面寫着『未識之神』。你們所不認識而敬拜的,我現在告訴你們。創造宇宙和其中萬物的神,既是天地的主,就不住人手所造的殿,也不用人手服事,好像缺少甚麼;自己倒將生命、氣息、萬物,賜給萬人。他從一本本:有古卷是血脈造出萬族的人,住在全地上,並且預先定準他們的年限和所住的疆界,要叫他們尋求神,或者可以揣摩而得,其實他離我們各人不遠;我們生活、動作、存留,都在乎他。就如你們作詩的,有人說:『我們也是他所生的。』我們既是神所生的,就不當以為神的神性像人用手藝、心思所雕刻的金、銀、石。世人蒙昧無知的時候,神並不監察,如今卻吩咐各處的人都要悔改。因為他已經定了日子,要藉着他所設立的人按公義審判天下,並且叫他從死裏復活,給萬人作可信的憑據。」
眾人聽見從死裏復活的話,就有譏誚他的;又有人說:「我們再聽你講這個吧!」於是保羅從他們當中出去了。 但有幾個人貼近他,信了主,其中有亞略‧巴古的官丟尼修,並一個婦人,名叫大馬哩,還有別人一同信從。

對基督徒來說,保羅這篇講道講的真好,不但講出了上帝的超越性(像是不住人手所造的殿、也不是金銀石的彫刻),也帶出了耶穌基督復活的大能。但最近我才注意到眾人的反應:「眾人聽見從死裏復活的話,就有譏誚他的;又有人說:「我們再聽你講這個吧!」」不曉得你看到這一段有什麼感想?可能我是玻璃心吧,如果我是保羅,我大概會非常非常的難過,看起來似乎沒有人理會這個福音、這篇講道。這篇被基督…

使用 Serial Port 來除錯的時候請小心

一般來說,程式設計師在除錯的時候常常會用的一種方式就是 print 大法,在程式適當的地方插入一些顯示資訊的指令,提供開發者更多資料來除錯。而在使用這個方法來除錯的時候,有很高的機會是利用 serial port 來顯示信息,特別是在嵌入式系統的開發上。然而當透過 serial port 來印信息的時候有著潛在的風險,因為在工作上遇到了,所以就特別紀錄在下面。首先先來看看下面這一段程式。

1
2
3
4
5
6
7
#!/usr/bin/python

import sys
import time

for item in range( 0, 10000, 1 ):
    print str( item ) + " ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"


這段程式相當的簡單,就只是單純的把一個字串印個 10000 次罷了。然後我們分別透過 SSH 以及 Serial port 連到測試設備上執行這個程式,並利用 time 這個指令來量測時間。結果記錄在下面(省略印字串的輸出)。

SSH:
root@OpenWrt:~# time ./test_print_01.py
real    0m 0.68s
user    0m 0.18s
sys     0m 0.08s


Serial Port (115200):
root@OpenWrt:~# time ./test_print_01.py
real    1m 8.18s
user    0m 0.17s
sys     0m 0.07s


可以發現時間差距非常的多,理由很簡單,因為 serial port 的輸出速度只有 115200 bps(本篇的實驗設備),所以慢也很正常的。問題是,如果今天要除錯的程式是一隻 time critical 的程式,那這就會遇到很大的麻煩。先把程式列在下面:

test_print.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/python

import sys
import time
import threading
from socket import *

BUFSIZE = 1024

class myThread (threading.Thread):
    def __init__( self, threadID, name, port ):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.port = port
    def run(self):
        print "Start UDP server: " + self.name + " (" + str( self.port ) + ")"
        s = socket( AF_INET, SOCK_DGRAM )
        s.bind( ( '', self.port ) )
        while 1:
            data, addr = s.recvfrom( BUFSIZE )
            print 'server received %r from %r' % (data, addr)
            s.sendto( data, addr )
        print "Exiting " + self.name

thread1 = myThread( 1, "Thread-1", 20000 )

thread1.start()

for item in range( 0, 500000, 1 ):
    print str( item ) + " ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"

test_print_client.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/python

import sys
import time
import datetime
from socket import *

BUFSIZE = 1024

addr = "127.0.0.1", 20000
s = socket(AF_INET, SOCK_DGRAM)
s.bind( ( '', 0 ) )

for item in range( 0, 100000, 1 ):
    time1 = datetime.datetime.now()
    print "[", time1, "]: Send"
    s.sendto( "++++++++++", addr )
    data, fromaddr = s.recvfrom( BUFSIZE )
    time2 = datetime.datetime.now()
    print "[", time2, "]: Recv %r from %r" % ( data, fromaddr )
    elapsedTime = time2 - time1
    print "Time Diff:", elapsedTime
    time.sleep(2)
    

上面這隻程式很簡單,說穿了就是開了一個 thread 來做 echo server,同時在 main thread 中拼命的印東西。另外一隻程式則是簡單的 echo client。接下來我們讓 test_print.py 分別在 SSH 以及 Serial Port 上面執行,client 的部分則統一在 SSH 上面執行,來看看會有甚麼差別。

SSH:
root@OpenWrt:~# ./test_print_client.py
[ 2017-04-17 13:55:14.600182 ]: Send
[ 2017-04-17 13:55:14.796277 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.196095
[ 2017-04-17 13:55:16.798956 ]: Send
[ 2017-04-17 13:55:16.842231 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.043275
[ 2017-04-17 13:55:18.844467 ]: Send
[ 2017-04-17 13:55:18.913060 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.068593
[ 2017-04-17 13:55:20.915303 ]: Send
[ 2017-04-17 13:55:20.922704 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.007401
[ 2017-04-17 13:55:22.924940 ]: Send
[ 2017-04-17 13:55:22.951737 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.026797


Serial Port:
root@OpenWrt:~# ./test_print_client.py
[ 2017-04-17 13:57:37.278359 ]: Send
[ 2017-04-17 13:57:39.991233 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:02.712874
[ 2017-04-17 13:57:41.993506 ]: Send
[ 2017-04-17 13:57:45.668543 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:03.675037
[ 2017-04-17 13:57:47.670792 ]: Send
[ 2017-04-17 13:57:51.346018 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:03.675226
[ 2017-04-17 13:57:53.346490 ]: Send
[ 2017-04-17 13:57:57.023386 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:03.676896
[ 2017-04-17 13:57:59.025634 ]: Send
[ 2017-04-17 13:58:02.700888 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:03.675254


可以看到 Serial Port 所需要的時間是 SSH 的數十倍。明明是同樣的程式,只是因為輸出界面的差異就可以在效能上有如此大的區別,所以在使用 print 大法的時候實在是應該要小心。

當然,剛剛那隻程式的 print 實在是太暴力了,我們稍微改寫一下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#!/usr/bin/python

import sys
import time
import threading
from socket import *

BUFSIZE = 1024

class myThread (threading.Thread):
    def __init__( self, threadID, name, port ):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.port = port
    def run(self):
        print "Start UDP server: " + self.name + " (" + str( self.port ) + ")"
        s = socket( AF_INET, SOCK_DGRAM )
        s.bind( ( '', self.port ) )
        while 1:
            data, addr = s.recvfrom( BUFSIZE )
            print 'server received %r from %r' % (data, addr)
            s.sendto( data, addr )
        print "Exiting " + self.name

thread1 = myThread( 1, "Thread-1", 20000 )

thread1.start()

for item in range( 0, 500000, 1 ):
    print str( item ) + " ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"
    time.sleep(0.005)

其實只是加上了 sleep( 0.005 )。為什麼是 0.005 ... 因為在工作上列印了太多的 log ,平均起來一秒印了 200 行,所以就先設定為 0.005 囉。結果如下:

SSH:
root@OpenWrt:~# ./test_print_client.py
[ 2017-04-17 14:10:51.235181 ]: Send
[ 2017-04-17 14:10:51.236046 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000865
[ 2017-04-17 14:10:53.236485 ]: Send
[ 2017-04-17 14:10:53.237083 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000598
[ 2017-04-17 14:10:55.239284 ]: Send
[ 2017-04-17 14:10:55.239859 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000575
[ 2017-04-17 14:10:57.242061 ]: Send
[ 2017-04-17 14:10:57.242655 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000594
[ 2017-04-17 14:10:59.244856 ]: Send
[ 2017-04-17 14:10:59.245456 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000600
[ 2017-04-17 14:11:01.246487 ]: Send
[ 2017-04-17 14:11:01.247073 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000586
[ 2017-04-17 14:11:03.249279 ]: Send
[ 2017-04-17 14:11:03.249872 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000593
[ 2017-04-17 14:11:05.252072 ]: Send
[ 2017-04-17 14:11:05.252653 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000581
[ 2017-04-17 14:11:07.254854 ]: Send
[ 2017-04-17 14:11:07.255434 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000580
[ 2017-04-17 14:11:09.256489 ]: Send
[ 2017-04-17 14:11:09.257069 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000580
[ 2017-04-17 14:11:11.259268 ]: Send
[ 2017-04-17 14:11:11.259870 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000602
[ 2017-04-17 14:11:13.262075 ]: Send
[ 2017-04-17 14:11:13.262657 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000582
[ 2017-04-17 14:11:15.264855 ]: Send
[ 2017-04-17 14:11:15.265425 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000570
[ 2017-04-17 14:11:17.266485 ]: Send
[ 2017-04-17 14:11:17.267076 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000591
[ 2017-04-17 14:11:19.269279 ]: Send
[ 2017-04-17 14:11:19.269852 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000573
[ 2017-04-17 14:11:21.272052 ]: Send
[ 2017-04-17 14:11:21.272616 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000564


Serial Port:
root@OpenWrt:~# ./test_print_client.py
[ 2017-04-17 14:08:34.943589 ]: Send
[ 2017-04-17 14:08:34.944421 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000832
[ 2017-04-17 14:08:36.946486 ]: Send
[ 2017-04-17 14:08:36.947092 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000606
[ 2017-04-17 14:08:38.949301 ]: Send
[ 2017-04-17 14:08:38.949905 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000604
[ 2017-04-17 14:08:40.952110 ]: Send
[ 2017-04-17 14:08:40.952706 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000596
[ 2017-04-17 14:08:42.954913 ]: Send
[ 2017-04-17 14:08:42.955494 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000581
[ 2017-04-17 14:08:44.956492 ]: Send
[ 2017-04-17 14:08:50.240876 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:05.284384
[ 2017-04-17 14:08:52.243117 ]: Send
[ 2017-04-17 14:08:52.243708 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000591
[ 2017-04-17 14:08:54.245913 ]: Send
[ 2017-04-17 14:08:54.246531 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000618
[ 2017-04-17 14:08:56.248738 ]: Send
[ 2017-04-17 14:08:56.249326 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000588
[ 2017-04-17 14:08:58.251531 ]: Send
[ 2017-04-17 14:08:58.252116 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000585
[ 2017-04-17 14:09:00.254326 ]: Send
[ 2017-04-17 14:09:00.254899 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000573
[ 2017-04-17 14:09:02.256485 ]: Send
[ 2017-04-17 14:09:02.257076 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000591
[ 2017-04-17 14:09:04.259290 ]: Send
[ 2017-04-17 14:09:08.467511 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:04.208221
[ 2017-04-17 14:09:10.468712 ]: Send
[ 2017-04-17 14:09:10.469497 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000785
[ 2017-04-17 14:09:12.471345 ]: Send
[ 2017-04-17 14:09:12.472161 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000816
[ 2017-04-17 14:09:14.473987 ]: Send
[ 2017-04-17 14:09:14.474775 ]: Recv '++++++++++' from ('127.0.0.1', 20000)
Time Diff: 0:00:00.000788


看起來結果差不多,不過 serial port 不定時會出現飆高的狀況。因此,在透過 Serial Port 使用 print 大法的時候,要記得這是會影響效能的。

PS. 在 python 上使用 threading 的話,使用了 Ctrl-C 來中止程式, thread 還是會繼續執行唷。 

留言

這個網誌中的熱門文章

如何將Linux打造成OpenFlow Switch:Openvswitch

我弟家的新居感恩禮拜分享:善頌善禱

如何利用 Wireshark 來監聽 IEEE 802.11 的管理封包