由於對 Google sheet 內建函式不常用,但腦海總浮現之前查過的印象,還是記錄一下好了。


Group 測試數據:

GroupColumn CountColumn SumColumn
AAA 10 100
BBB 20 200
CCC 30 300
AAA 40 400

GroupColumn 進行 GroupBy 預期應該是:

GroupColumn CountColumn SumColumn
AAA 50 500
BBB 20 200
CCC 30 300

語法:

1
=QUERY(rawData!A1:C4,"select A, count(B), sum(C) group by A")
  • rawData 為 sheet 名稱
  • A1:C4 為資料範圍

如果想要替 Column 命名,需使用 label 語法,例如 label A 'AliasName'

Read more »

本文介紹改用 Lua 方式存取 Redis,以省下連線、存取次數。

Demo內容

  1. 先在 redis 建立一個 key
  2. 以 lua 方式執行,把值取出來,加上整數 123,寫回去 redis
  3. 以一般指令方式,把值取出來,加上整數 123,寫回去 redis

建立連線機制

1
2
3
4
5
private const string RedisHost = "127.0.0.1:6379";
private const string TestKey = "TestRedisKey";

using var conn = await ConnectionMultiplexer.ConnectAsync(RedisHost);
var redisDb = conn.GetDatabase();

一般存取方式

當有一些邏輯比較複雜就必須把值取回程式中運算。

1
2
3
4
5
6
7
8
9
10
11
12
private static async Task RunWithoutLua(IDatabase db)
{
var currentValue = await db.StringGetAsync(TestKey);

// Some complicated logic in C#
var newValue = Convert.ToInt32(currentValue) + 123;
await db.StringSetAsync(TestKey, newValue);

// Validate
var afterUpdatedValue = await db.StringGetAsync(TestKey);
Console.WriteLine($"RunWithoutLua: After updated value: {afterUpdatedValue}");
}

用 Lua 方式存取

這邊是示意才用這種方式寫,但大型專案還是建議把 .lua 整理起來分類放在資料夾內,這樣 repository 層比較乾淨,也不會有過多、複雜的邏輯。

Read more »

Docker-compose 設定檔注意事項 這篇文章的範例中,我們使用了 MongoDb 的容器。yml 如下:

1
2
3
4
5
6
7
8
version: '3'
services:
mongo-local-test.com:
image: mongo
container_name: mongodb_cotainer
ports:
- "27117:27017"
entrypoint: [ "/usr/bin/mongod","--bind_ip", "localhost,mongo-local-test.com"]

好處是每次開啟都是全新的,不用擔心資料弄髒弄壞,但如果想保留資料怎麼辦?這時候需要使用到 volumes 設定了。

1
2
volumes:
- '~/Desktop/mount-mongo-data:/data/db'

: 之前的是實體位置,之後的是 container 內的位置。

設定完後 docker-compose up / down 就可以看到實體檔案在該路徑上了。如下:

1
2
3
4
5
6
7
8
➜  mount-mongo-data ls
WiredTiger _mdb_catalog.wt index-1-6246240698095516127.wt mongod.lock
WiredTiger.lock collection-0-6246240698095516127.wt index-3-6246240698095516127.wt sizeStorer.wt
WiredTiger.turtle collection-2-6246240698095516127.wt index-5-6246240698095516127.wt storage.bson
WiredTiger.wt collection-4-6246240698095516127.wt index-6-6246240698095516127.wt
WiredTigerHS.wt diagnostic.data journal
➜ mount-mongo-data pwd
/Users/mingyi/Desktop/mount-mongo-data

總不可能每次都指定實體位置吧~這樣要維護也很困難,另一種方式就跟其他 container 的 voulume 一樣放置,語法如下:

1
2
3
4
5
6
7
8
9
10
11
12
version: '3'
volumes:
mongo-mount-data:

services:
mongo-local-test.com:
image: mongo:latest
container_name: mongo_latest
ports:
- "27117:27017"
volumes:
- mongo-mount-data:/data/db
Read more »

在使用 lua 的 unpack 語法一定要特別注意,如果已經知道參數的數量,那會強烈建議不要使用 unpack。

測試條件

  • 迴圈執行次數 一百萬
  • table 長度 5

選手一 unpack

1
2
3
4
5
local style1 = function()
for i=1, loopCount do
local v1,v2,v3,v4,v5 = table.unpack(table_a)
end
end

選手二 get value directly

1
2
3
4
5
6
7
8
9
local style2 = function()
for i=1, loopCount do
local v1 = table_a[1]
local v2 = table_a[2]
local v3 = table_a[3]
local v4 = table_a[4]
local v5 = table_a[5]
end
end

結果

1
2
elapsed: 75.28 ms  // style1: unpack
elapsed: 0.40 ms // style2

結論

Read more »

本文 sample code 可以改為 pass by function 方式更為簡潔,但之前文章就先不改動了。
可以參考這篇文章的寫法。


在專案中,對 redis 操作都已經改成全 lua 執行,因為是使用 redis 的關係,對此操作頻率肯定很高。前陣子經同事提醒,關於某些語法效能並不太好,因此對 for, pair, ipair 再次檢驗其效能。

測試條件

  • 迴圈執行次數 一百萬
  • table 長度 1000

選手一 for

1
2
3
4
5
for i=1, loopCount do
for i=1, #table_a do
x = table_a[i]
end
end

選手二 for with local variable length

1
2
3
4
5
6
for i=1, loopCount do
local leng = #table_a
for i=1, leng do
x = table_a[i]
end
end

選手三 pair

Read more »

在管理時,會需要監控哪些對 Redis 的操作比較慢(久),就有點像是 database 的 profiler 概念,會記錄所有慢的操作。

特別注意:

  • SLOWLOG 僅紀錄實際執行的時間,不包含來回請求或等待執行的時間
  • SLOWLOG 都是存在快取內,因此對效能影響很些微,可以放心在線上使用

設定 SLOWLOG 記錄門檻

SLOWLOG 有一個毫秒的門檻,超過就會被列入 SLOWLOG(default: 10ms)。要修改的話可以直接改 redis.conf 或是使用 config 指令。

執行時間超過 100ms:

1
CONFIG SET slowlog-log-slower-than 100

SLOWLOG 紀錄數量

SLOWLOG 最多需要保留幾筆(default:10筆),超過的話會先擠掉最舊的(FIFO)。

設定最多保留100筆

Read more »

結論:該使用什麼,沒有最正確,只有最適合。本篇文章選擇的方向,比較適合我在工作上遇到的情境,不見得看官也適用。

前提

冒險開始

很自然的,遇到時間,在C#階段我們會使用 DateTimeOffset,接著就很開心的存進 MongoDB。
打開MongoDB發現該欄位跟我們想得不太一樣,

alt

沒錯,DateTimeOffsetNow 變成一個陣列,裡面存的是 DateOffset,在sub document上加上 Index 絕對不是一件好事。

捨棄Offset!把它變成UTC DateTime格式吧!

哇~蒸蚌,這下欄位變成上圖的 DateTimeNow 欄位,沒有陣列了。
沒錯,這樣存進去就會變成只有一個欄位的 Date,但是這樣就夠了嗎?
經驗上這種時間格式一定都會拿來查詢條件,而查詢條件就是拿來比較的,介於~大小於這種,而這個比較的效率好嗎?肯定不會比數字來得好,就像比較字串效能還是輸給直接比較數字。

通通拿去轉Tick

Read more »

Visual studio code 已經是開發者必備的工具之一,我個人的操作上不喜歡使用內建的 Command+O 開啟功能,尤其很常在使用 terminal 時需要開啟 IDE 來編輯,所以在 terminal 使用指令 vs code 就很重要了。

設定

  1. 在 vs code 中同時按下 command + shift + p
    alt

  2. 點選 Shell Command: Install 'code' command in PATH

大功告成~

使用

只要在 terminal 輸入 code 即可開啟 vs code 囉!
但只輸入 code 只會開啟一個空白的 vs code,我通常都是會在該路徑輸入 code . 這樣會直接開啟該目錄 explorer。


這篇比較像是我自己的備忘錄,因為新環境只要設定一次,久了根本就忘記了

Read more »

事前準備

我們先將 Consul 以 docker 方式啟動

1
2
3
4
5
6
7
8
version: '3'
services:
consul-local-test.com:
image: consul:latest
container_name: consul-local-test.com
ports:
- "8500:8500"
command: ["consul", "agent", "-dev", "-client=0.0.0.0"]

接著使用瀏覽器進入Consul自帶的管理介面http://localhost:8500/

alt

點選上方 Key/Value 就可以開始編輯了
範例直接使用json格式填入

1
2
3
4
{
"Key1": 100,
"Key2": "HelloConsul"
}

這邊要特別注意的是 value 所儲存的值不可以超過 512kb

今天介紹的工具就是免費、開源的 BenchmarkDotNet
這個工具能夠協助你快速完成速度的測試,不需要再像以前一樣寫滿StopWatch、手動整理跑完的數據,最後再把計時用的程式碼還原。
透過這個工具,只需要短短幾個步驟就可以取得對照的結果。

首先需要下載、安裝這個套件。

1
Install-Package BenchmarkDotNet
Read more »

最近需要做一個小工具去整理出指定資料夾所有使用的第三方套件版本,同時去查詢nuget最新版本號。
拆解步驟大概就是兩個

  • 掃出使用套件清單
  • 以這個清單查尋nuget最新版本

透過以下語法找出所有 .csproj 檔名的檔案,並找到第三方套件的內容。
我們找一個 csproj 範例如下:

1
2
3
4
5
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
</ItemGroup>
</Project>

透過以下語法找到檔案並解析內容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//找出所有 .csproj 檔案
var allFiles = Directory.GetFiles(arg, "*.csproj", SearchOption.AllDirectories);
//依序以 XDocument 載入並解析出第三方套件的名稱與版本號
foreach (var file in allFiles)
{
var projDefinition = XDocument.Load(file);
var elements = projDefinition.Element("Project")?.Element("ItemGroup")?.Elements("PackageReference");

if (elements == null)
continue;
if (!elements.Any())
continue;
var pkgRefs = elements.ToDictionary(x => x.Attribute("Include")?.Value, x => x.Attribute("Version")?.Value);
}

剩下的功能就是查詢 Nuget 取得版本號碼。
由於大部分人的使用都是直接使用 IDE 或 VS 的 package management console 來安裝,幾乎沒有使用 api 去呼叫的需求,這類型的資訊在網路上很少;若是哪天要整理的內容變很多時,手動就感覺特別的沒有效率。 我絕對不會承認官方文件看好久還是看不懂

透過 Package 名稱去查詢版本號碼其實並不太難,在 v3 api 中格式如下:

1
https://api.nuget.org/v3-flatcontainer/{PackageName}/index.json

只要把{PackageName}替換成套件名稱即可。而 Nuget 會回傳一個 json 格式資料,我們以查詢 Newtonsoft.Json 套件為例。
Url example:

Read more »