2020年5月31日日曜日

Dockerの勉強

AWS LambdaをいきなりCALLしてもらうのは、難しいかもしれないので、ローカルでデバッグできる環境を提供しようと思いました。必要なのは、C++lambdaが動かせること、ローカルでDynamodbにlambdaがW/Rできることです。

https://github.com/lambci/docker-lambda
https://aws.amazon.com/jp/serverless/sam/

を理解出来れば、そういったキットを提供できるかもしれません。いずれも、Dockerなる仮想化技術が使われているので、Dockerを勉強する必要があります。

本もいくつか買ってみたのですが、このサイトの記事が私的にはよさそうでした。

https://kirohi.com/docker_study_resources

2020年5月29日金曜日

C++11/C++17へ

AWS用の記述では、C++14 をベースとして、部分的にC++17を使用しています。例えば、WindowsとLinux、スレッド生成一つ取ってもC++11を使えば、共通のstd::thread が使えます。ファイルのアクセスについてもC++17では、filesystemがあり、便利に使えます。ということで、同じ事をやるのに書き換えてWindows/Linux共通で使えるようにした部分が多数あります。

恐らく現リリース最新版129CとAWS開発最新版では、1万行以上記述が変わっています。そのためRegression Testが必要となっています。

このテストが1週間、マニュアル更新に1週間、リリースは、6月中旬を予定しています。



2020年5月28日木曜日

Python Editor の改善

次期リリース予定版(現在開発中のAWS対応版)では、PythonEditor(scintilla)を少し改善しています。Python Editorは、二つのタブになりました。[ソース]と[ソース全体]です。[ソース]は今までのエディタに同じです。


[ソース全体]の方は、ReadOnlyなので書くことはできません。また、最初の状態では、何もありません。
 求解すると、以前の_property.py と現在のソースとが合体したソースを[ソース全体]タブ中に見ることができます。


ここで、故意にエラーを作ってみます。今月:の:を削除して求解してみます。



 当然エラーになります。
● 
行をダブルクリックすると当該行がピンクでハイライトされます。
 
 
 ソース全体は、ソルバーが内蔵しているpython interpreterが認識しているソース全体になります。
従い、今までと違い正しく当該行を表示することが出来ます。
また、pythonソースを記述するのに、外部エディタを参照しながら記述する面倒が少し改善されます。

内部動作として、~property.pyは、以前と同様に出力されています。GUIは、それを拾ってきて、[ソース全体]として表示しています。GUIは、python interpreterの出力する"<string>"をKeywordとして、findしたら、python editorにその後続の(行)を表示されています。

AWS版でも、同様ですが、ファイル出力というインタフェースは利用できません。代わりに
lambda call のresponce payload中にソース全体が返ります。また、求解状況は,ユーザアカウント上の指定する(lambdaがアクセス許可された)テーブル上のStatusに出力されます。Status
は、XXsecに一回更新されます。(streaming modeにしてすると、上記GUI画面の右ペイン相当を得ることが出来ます。) 従い、AWSユーザは、(やろうと思えば)上記GUI動作と同じ処理を行うことが出来ます。

2020年5月27日水曜日

AWS 構成変更

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/gettingstarted-limits.html
によるとpayload sizeの上限は、リクエスト・レスポンスで、6MBになっています。勘違いしていたのですが、往復計で6MBではなく、リクエスト6MB、レスポンス6MBということみたいです。とすれば、レスポンスで、解とpython property fileを返しても問題ないので、そのように設計変更しました。(今までは、dynamodbに出力するようにしていました。)下図が、変更後の構成とシーケンス図になります。


下がレスポンスの結果でpythonチュートリアル1の求回数を2にしたときのログになります。
 
Calling lambda..SC3_Lambda_Engine problem.json  clientConfig.requestTimeoutMs=900000sec
1:{
2: "peak_memory": "527.921875MB",
3: "result": "{\n  \"solution1.txt\":{\n    \"スタッフ名1\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名10\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名11\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名12\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名13\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名14\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名15\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名16\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名17\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名18\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"日勤\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名2\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名3\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名4\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名5\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名6\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名7\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名8\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名9\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"]\n  },\n  \"solution2.txt\":{\n    \"スタッフ名1\":[\"入り\",\"公休\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名10\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名11\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名12\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名13\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名14\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名15\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名16\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名17\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名18\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"日勤\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名2\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名3\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名4\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名5\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名6\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名7\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名8\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"],\n    \"スタッフ名9\":[\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\",\"入り\"]\n  }\n}\n",
4: "python": "#staffdef\nstaffdef=['スタッフ名1','スタッフ名2','スタッフ名3','スタッフ名4','スタッフ名5','スタッフ名6','スタッフ名7','スタッフ名8','スタッフ名9','スタッフ名10','スタッフ名11','スタッフ名12','スタッフ名13','スタッフ名14','スタッフ名15','スタッフ名16','スタッフ名17','スタッフ名18']\n#daydef\n制約開始日=5\n制約終了日=35\n表示開始日=0\ndaydef=['2016-07-27','2016-07-28','2016-07-29','2016-07-30','2016-07-31','2016-08-01','2016-08-02','2016-08-03','2016-08-04','2016-08-05','2016-08-06','2016-08-07','2016-08-08','2016-08-09','2016-08-10','2016-08-11','2016-08-12','2016-08-13','2016-08-14','2016-08-15','2016-08-16','2016-08-17','2016-08-18','2016-08-19','2016-08-20','2016-08-21','2016-08-22','2016-08-23','2016-08-24','2016-08-25','2016-08-26','2016-08-27','2016-08-28','2016-08-29','2016-08-30','2016-08-31']\n#staffcollection\n全スタッフ=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\n入り=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\n公休=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\n日勤=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\n明け=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]\nタスク1=[]\nタスク2=[]\nタスク3=[]\nNoTaskVar=[]\n\n#daycollection\n今月=[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,33,34,35]\n日=[4,11,18,25,32]\n月=[5,12,19,26,33]\n火=[6,13,20,27,34]\n水=[0,7,14,21,28,35]\n木=[1,8,15,22,29]\n金=[2,9,16,23,30]\n土=[3,10,17,24,31]\n全日=[0,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,33,34,35]\n祝=[15]\n振=[]\n平日=[0,1,2,5,6,7,8,9,12,13,14,15,16,19,20,21,22,23,26,27,28,29,30,33,34,35]\n週末=[3,4,10,11,17,18,24,25,31,32]\n休日=[3,4,10,11,15,17,18,24,25,31,32]\n稼働日=[0,1,2,5,6,7,8,9,12,13,14,16,19,20,21,22,23,26,27,28,29,30,33,34,35]\n制約開始日一日前=[4]\n制約開始日二日前=[3]\n制約開始日三日前=[2]\n制約開始日四日前=[1]\n制約開始日五日前=[0]\n制約開始日六日前=[]\n制約開始日七日前=[]\n制約開始日P1=[6]\n制約開始日P2=[7]\n制約開始日P3=[8]\n制約開始日P4=[9]\n制約開始日P5=[10]\n制約開始日P6=[11]\n第一週=[5,6,7,8,9,10,11]\n第二週=[12,13,14,15,16,17,18]\n第三週=[19,20,21,22,23,24,25]\n第四週=[26,27,28,29,30,31,32]\n第五週=[33,34,35]\n第六週=[]\n四週間=[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]\n制約開始日1日前から=[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,33,34,35]\n制約開始日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,33,34,35]\n制約開始日3日前から=[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,33,34,35]\n制約開始日4日前から=[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,33,34,35]\n制約開始日5日前から=[0,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,33,34,35]\n制約開始日6日前から=[0,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,33,34,35]\n制約終了日六日前=[29]\n制約終了日五日前=[30]\n制約終了日四日前=[31]\n制約終了日三日前=[32]\n制約終了日二日前=[33]\n制約終了日一日前=[34]\n金土日=[2,3,4,9,10,11,16,17,18,23,24,25,30,31,32]\n金土日月=[2,3,4,5,9,10,11,12,16,17,18,19,23,24,25,26,30,31,32,33]\n\n#shiftcollection\n\n#classcollection\n全スタッフ属性=[全スタッフ]\n\n#shiftdef\nshiftdef={'入り':入り,'公休':公休,'日勤':日勤,'明け':明け}\n#taskdef\ntaskdef={'タスク1':タスク1,'タスク2':タスク2,'タスク3':タスク3,'NoTaskVar':NoTaskVar}\n#non_auto_tasks\nnon_auto_tasks=[]\n#phase_list\n\n#task collections\n#digited group\n#column_constraints\n週末入り強制=(True,('週末',週末),'',入り,('',''),全スタッフ,2,-1,-1,-1.000000,-1.000000,0,0)\n列制約グループ1={'週末入り強制':週末入り強制}\n列制約グループ2={}\ncolumn_constraints={'列制約グループ1':列制約グループ1,'列制約グループ2':列制約グループ2}\n#shift schedules\nshift_schedules=[[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n,[('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0),('',0)]\n]\ntask_schedules=[[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n,[]\n]\n"
5:}
Elapsed time(C++):4947[ms]
 
大変に見にくいのは、ESCAPE シーケンスが挿入されてしまうためだと思われます。解は、peak_memory出力の後、solution1.json, (solution1_task.json),solution2.json,(solution2_task.json)...でJsonフォーマットで出力されます。taskは、フェーズモードでの記述があった場合のみ、出力されます。その後、python記述があれば、python_property.pyが出力されます。
 
レスポンスpayload生成部C++ソースを以下に示します。
 
 
 Aws::Utils::Json::JsonValue jsonPayload;
    string peak_memory=std::to_string(memUsedPeak())+"MB";
      
    jsonPayload.WithString("peak_memory", peak_memory);
    jsonPayload.WithString("result", json_solution);
    jsonPayload.WithString("python",python_property_src);
    string str= jsonPayload.View().WriteReadable();
  
  
    return aws::lambda_runtime::invocation_response::success(str,"application/json");

2020年5月26日火曜日

AWS Lambda-メモリリーク対策C++

設計を大幅に変更しました。行数にして数千行程度、Editしたと思います。

サーバアプリでは、基本的にメモリリークは許されません。が、Lambdaは、毎回HotStartする訳でもないので、目標として、一回のメモリリークは、100KB程度以下としました。(1000回連続HotStartされても100MBの増加に留まる、としました。) 1000回連続で来ることはないという想定です。これが崩れることがあるとするなら、同じLambdaを複数用意すれば事足ります。

<メモリリーク対策の為の設計変更>
次の対策方法を検討しました。

A)shared_ptrの使用
shared_ptrの場合、unionで、ptrを複数定義している部分の回避が面倒。(一応C+11なら書けそうですが..) さらに、performanceの劣化、メモリ増大が懸念されます。さらに、困難なのは変更Edit量が半端ないことです。

B)独自アロケータの使用
shared_ptr使用の場合に比べて、全ての面で優れています。union ptrの変更の必要はありませんし、変更Edit量も最小で済みます。
関連するクラス(ptr参照しているクラス)は、10種以下なので、それら全てを独自アロケータを使って処理します。つまり、delete処理は、最後の一回のみです。ptrを辿ってdeleteしていくことはしません。ですのでクラスのnew ptrは、管理しません。その結果、クラス内のstd::vectorにも細工が必要になります。幸い、std::vectorは、アロケータインタフェースが定義されているので、それらを含めて関連クラスのdelete処理を一気に行う処理が書けます。shared_ptrで、ちまちま参照カウントする方式に比べて速度で10倍くらい違う気がします。(しかし、ここは、ボトルネックではないので、体感では変わりません。)

 


<メモリリーク対策検証>
1)VisualC++内蔵ヒープチェック
メモリリークをEnableします。_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); また、リンカーのDebugを 共有と公開用に最適化されたデバッグ情報の生成 (/DEBUG:FULL)に設定します。(なぜか、デバッグ出力が全くされなかったのでが、VisualStudioの修復 を行ったらデバッグ出力が出るようになりました。)

2)VisualLeakDetectorの活用
1)では、ソース行が殆ど表示されないので分かりずらいです。格段に遅くはなりますが、デバッグ初期は、VisualLeakDetectorを使いました。スタックトレースまで表示されるので、場所の特定は容易です。しかし、ある程度以上の規模になると原因不明のエラーが出ることがありました。そのときは、VisualC++のヒープチェックに頼ることになります。

3)検証
■Windows: VisualC++/Visual Leak Detectorによる検証
■Linux:         g++ -fsanitize=leak による検証
■mainを何回か廻して、取得メモリ量に変化ないことを確認(ptrのリセット処理等検証)

4)メモリリーク箇所
■旧言語制約は、deprecatedで基本使用禁止とします。なので放置です。
■algorithm4 これもAWSではサポートしません。なので放置です。
■python インタフェース: 最新版で少し改善しましたが、僅かに未だ残っているようです。こちらは、改版に期待ということで、放置しています。
■Error 解がなかった場合、原因解析処理でメモリリークします。課題です。
■未検証 TASK周り

5)Tips
 ■Windowsは、OKで、LinuxでNGな箇所がありました。g++ stringstream.str()に要注意です。
 ■new vector<...> を vector<> 形式にして、出来る限りスタック上で自動deleteとするように書き換えました。地道な作業ですが、普段から、明示deleteしなくてもよい書き方を意識して書くべきだったと、反省しています。

<結論>
■従い、Algorithm1で、pythonを使わずに,解があるのであれば、メモリリークはありません。
■pythonを使った場合、記述量に関係なく、constantに1KB以下程度がリークします。1000回呼んで1MB以下です。しかし、解がなかったときの原因解析でリークが発生します。この部分が課題です。
■大幅にいじってしまったので、regression test が必要です。







2020年5月18日月曜日

Zoom オンラインコンサルティングを始めました。

娘が、大学のオンライン授業で使っていて、「知らないの? 遅れているね!」と言われてしまいました。中々良さそうなので、使ってみることにしました。

ついでに、有料でオンラインコンサルティングを始めることにしました。予約制で、単発~1時間5000円です。これまで、ありそうでなかったコンサルティングです。

勤務表の自動勤務表化に関わるコンサルティングです。所属を伏せて顔なしでも可能です。画面共有で、スケジュールナースの操作方法等も直接に指導可能です。勤務の制度設計、工場の変則勤務等、自動勤務化に関わるあらゆるご相談に応じます。 スケジュールナースの使い方レッスンも可能です。




2020年5月17日日曜日

mimallocの評価

こちらで、大変に詳しく解析をされています。
https://qiita.com/methane/items/e88901b7392c10cee2c9
pythonのmalloc置き換え用度では、glibcに比べてよろしくない、という結果のようです。

私のエンジンは、数十バイト規模のメモリを大量に消費しますので、それをシミュレーションする意味で、以下のソースを書きました。(Visual Studio 2019 mimalloc-override-testから書き換えDebugビルド)

ここで、取得しているメモリは、9バイトから始まって、およそ2KBまで、メモリを1バイトづつインクメンタルに取得しています。それを1ブロックとして1000個取得します。理論上の取得メモリは、公差1の等差数列で計算でき、およそ2GBです。(きっちり詰めたときおよそ2GB消費します。)

int main() {

    mi_stats_reset();  // ignore earlier allocations
    mi_heap_t* heap = mi_heap_new(); 
    mi_heap_t* old = mi_heap_set_default(heap);
    for (auto i = 0;i < 1000;i++) {
        for (auto j = 0;j < 2000;j++) {
            char* p = new char[9+j];
        }
        
    }
    
  //  mi_heap_destroy(heap));
    mi_stats_print(NULL);
    return 0;
}
heap stats:     peak      total      freed       unit      count
normal   4:   501.9 kb   501.9 kb       0 b       32 b     16.0 k   not all freed!
normal   6:   752.9 kb   752.9 kb       0 b       48 b     16.0 k   not all freed!
normal   8:  1003.9 kb  1003.9 kb       0 b       64 b     16.0 k   not all freed!
normal   9:     1.2 mb     1.2 mb       0 b       80 b     16.0 k   not all freed!
normal  10:     1.4 mb     1.4 mb       0 b       96 b     16.0 k   not all freed!
normal  11:     1.7 mb     1.7 mb       0 b      112 b     16.0 k   not all freed!
normal  12:     1.9 mb     1.9 mb       0 b      128 b     16.0 k   not all freed!
normal  13:     4.8 mb     4.8 mb       0 b      160 b     32.0 k   not all freed!
normal  14:     5.8 mb     5.8 mb       0 b      192 b     32.0 k   not all freed!
normal  15:     6.8 mb     6.8 mb       0 b      224 b     32.0 k   not all freed!
normal  16:     7.8 mb     7.8 mb       0 b      256 b     32.0 k   not all freed!
normal  17:    19.5 mb    19.5 mb       0 b      320 b     64.0 k   not all freed!
normal  18:    23.4 mb    23.4 mb       0 b      384 b     64.0 k   not all freed!
normal  19:    27.3 mb    27.3 mb       0 b      448 b     64.0 k   not all freed!
normal  20:    31.2 mb    31.2 mb       0 b      512 b     64.0 k   not all freed!
normal  21:    78.1 mb    78.1 mb       0 b      640 b    128.0 k   not all freed!
normal  22:    93.7 mb    93.7 mb       0 b      768 b    128.0 k   not all freed!
normal  23:   109.3 mb   109.3 mb       0 b      896 b    128.0 k   not all freed!
normal  24:   125.0 mb   125.0 mb       0 b      1.0 kb   128.0 k   not all freed!
normal  25:   312.5 mb   312.5 mb       0 b      1.2 kb   256.0 k   not all freed!
normal  26:   375.0 mb   375.0 mb       0 b      1.5 kb   256.0 k   not all freed!
normal  27:   437.5 mb   437.5 mb       0 b      1.7 kb   256.0 k   not all freed!
normal  28:   437.5 mb   437.5 mb       0 b      2.0 kb   224.0 k   not all freed!
normal  30:     3.0 kb     3.0 kb       0 b      3.0 kb       1     not all freed!

heap stats:     peak      total      freed       unit      count
    normal:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
      huge:       0 b        0 b        0 b        1 b              ok
     giant:       0 b        0 b        0 b        1 b              ok
     total:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
malloc requested:          1.8 gb

  reserved:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
 committed:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
     reset:       0 b        0 b        0 b        1 b              ok
   touched:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
  segments:     531        531          0                           not all freed!
-abandoned:       0          0          0                           ok
   -cached:       0          0          0                           ok
     pages:    33.3 k     33.3 k        0                           not all freed!
-abandoned:       0          0          0                           ok
 -extended:   590.2 k
 -noretire:       0
     mmaps:       8
   commits:     577
   threads:       0          0          0                           ok
  searches:     0.9 avg
numa nodes:       1
   elapsed:      16.793 s
   process: user: 15.984 s, system: 0.765 s, faults: 545698, reclaims: 0, rss: 2.0 gb, commit charge: 2.0 gb
 
当然のことながら、個別オブジェクトをdeleteしていないので、freeでないと言ってきます。
次に、コメントアウトしていた、mi_head_destroy(heap)をEnableしてみます。

すると、以下のように、良い感じになりました。9バイトから始めたのは、8バイトだと何故かフリーされなかったからです。(??)  とりあえず、良さそうなので、実装してみようかなと思います。
ドキュメントによれば、Windowsでは、古い実装にAddOnするだけで、new/malloc オーバライドすることが出来るそうです。Linuxへのポートも当然サポートされているので、前に示した要件がクリアされています。しかし、未だ枯れていないので、注意は必要です。(最新のビルドは数日前でした。)
 
int main() heap stats:     peak      total      freed       unit      count
normal   4:   501.9 kb   501.9 kb   501.9 kb      32 b     16.0 k   ok
normal   6:   752.9 kb   752.9 kb   752.9 kb      48 b     16.0 k   ok
normal   8:  1003.9 kb  1003.9 kb  1003.9 kb      64 b     16.0 k   ok
normal   9:     1.2 mb     1.2 mb     1.2 mb      80 b     16.0 k   ok
normal  10:     1.4 mb     1.4 mb     1.4 mb      96 b     16.0 k   ok
normal  11:     1.7 mb     1.7 mb     1.7 mb     112 b     16.0 k   ok
normal  12:     1.9 mb     1.9 mb     1.9 mb     128 b     16.0 k   ok
normal  13:     4.8 mb     4.8 mb     4.8 mb     160 b     32.0 k   ok
normal  14:     5.8 mb     5.8 mb     5.8 mb     192 b     32.0 k   ok
normal  15:     6.8 mb     6.8 mb     6.8 mb     224 b     32.0 k   ok
normal  16:     7.8 mb     7.8 mb     7.8 mb     256 b     32.0 k   ok
normal  17:    19.5 mb    19.5 mb    19.5 mb     320 b     64.0 k   ok
normal  18:    23.4 mb    23.4 mb    23.4 mb     384 b     64.0 k   ok
normal  19:    27.3 mb    27.3 mb    27.3 mb     448 b     64.0 k   ok
normal  20:    31.2 mb    31.2 mb    31.2 mb     512 b     64.0 k   ok
normal  21:    78.1 mb    78.1 mb    78.1 mb     640 b    128.0 k   ok
normal  22:    93.7 mb    93.7 mb    93.7 mb     768 b    128.0 k   ok
normal  23:   109.3 mb   109.3 mb   109.3 mb     896 b    128.0 k   ok
normal  24:   125.0 mb   125.0 mb   125.0 mb     1.0 kb   128.0 k   ok
normal  25:   312.5 mb   312.5 mb   312.5 mb     1.2 kb   256.0 k   ok
normal  26:   375.0 mb   375.0 mb   375.0 mb     1.5 kb   256.0 k   ok
normal  27:   437.5 mb   437.5 mb   437.5 mb     1.7 kb   256.0 k   ok
normal  28:   437.5 mb   437.5 mb   437.5 mb     2.0 kb   224.0 k   ok
normal  30:     3.0 kb     3.0 kb     3.0 kb     3.0 kb       1     ok

heap stats:     peak      total      freed       unit      count
    normal:     2.0 gb     2.0 gb     2.0 gb       1 b              ok
      huge:       0 b        0 b        0 b        1 b              ok
     giant:       0 b        0 b        0 b        1 b              ok
     total:     2.0 gb     2.0 gb     2.0 gb       1 b              ok
malloc requested:          1.8 gb

  reserved:     2.0 gb     2.0 gb       0 b        1 b              not all freed!
 committed:     2.0 gb     2.0 gb   196.5 mb       1 b              not all freed!
     reset:       0 b        0 b        0 b        1 b              ok
   touched:     2.0 gb     2.0 gb     2.0 gb       1 b              ok
  segments:     531        531        531                           ok
-abandoned:       0          0          0                           ok
   -cached:       0          0          0                           ok
     pages:    33.3 k     33.3 k     33.3 k                         not all freed!
-abandoned:       0          0          0                           ok
 -extended:   590.2 k
 -noretire:       1
     mmaps:       8
   commits:     577
   threads:       0          0          0                           ok
  searches:     0.9 avg
numa nodes:       1
   elapsed:      31.050 s
   process: user: 29.953 s, system: 0.765 s, faults: 545700, reclaims: 0, rss: 2.0 gb, commit charge: 2.0 gb

2020年5月16日土曜日

C++メモリリークの対処方法の検討

3案あります。

1)unique_ptr,shared_ptr を使う
2)終了時にまとめてobjectをdeleteする。その際、unordered_set<void*> に記憶させてdouble deleteを防止する。
3)独自のアロケータを使う

1)でunique_ptrで書けるところは、書き直してみました。しかし、shared_ptrを使うとなるとruntime 性能の劣化が気になります。基本的には、C#や、JAVAがやっている参照カウント方式です。書き直しにも膨大な手間が必要でバグなしに書き直すのは至難です。

2)案では、runtime性能の劣化は軽微でしょう。Desktop版では、deleteしなければ、peformanceの劣化は、原理上ありません。しかし、サーバ版では、やはりこまめに、leak箇所を潰していく作業が必要となります。1)案よりは良さそうですが、作業量は未だ多そうです。

3)tcmalloc,jemalloc,nedmalloc,miallocを使う
これらは、小メモリに対しては、threadに対するヒープを備えているはずです。new/delete をオーバライドして、thread 消滅時にそのヒープを開放してやれば、one go で行けるはずです。要件としては、それらのhackが可能であることとLinux/Windows の両方にポート可能であること、さらには、statisticsも出力可能であること、そんなライブラリがあればよいのです。

考えてみれば、サーバアプリケーションでは、メモリの回収機構は、備えていなければなりません。今の時代、C/C++で、サーバアプリというのは、考えられないことかもしれませんが、究極の性能を提供する計算サーバという視点でみるならば、現時点のみならず今後も必要なような気がします。
その意味で、C++の進化は、必要なことであると理解できます。






2020年5月15日金曜日

Lambda のインスタンス寿命

C++ lambdaをColdStart出来ればよいのですが、制御できる方法は見つけられませんでした。

実験してみると、10分程度以内に再アクセスがある場合、インスタンスを再利用するようです。
これをHotStartと呼んでいるようです。インスタンスをプロセスから立ち上げる場合が、ColdStartとなります。これを避けるために、常にHotな状態にする、つまり常にアクセスするなどの対策が取る場合もあるようです。

で、C++の場合の問題なのですが、メモリマネージをちゃんとしないといけないという問題です。
今まで、一回CALLごとにプロセスを立ち上げたので、その必要はなかったのですが、インスタンスを再利用するとなると、メモリリークを潰す必要があります。

仮に、メモリ取得のピークが一瞬でも設定最大の3GBを超えると落ちてしまいます。どんな具合か、とりあえずAWS上で、ピークメモリを取得してみました。メモリ取得ソースは以下です。

インスタンスは、サンプルで添付している正循環8回です。(Windows上での実行時間とほぼ同じ時間70sec程度となっていますので、性能的には、通常PCで行うのと大差ないと思われます。
ちなみに、AWS上の性能は、メモリ設定に比例するらしいので、最大性能でもPC程度と推定されます。AWSの設定は、3GB、タイムアウト15分にしています。




static inline int memReadPeak(void) 
 { 
     char  name[256]; 
     pid_t pid = getpid(); 
 

     sprintf(name, "/proc/%d/status", pid); 
     FILE* in = fopen(name, "rb"); 
     if (in == NULL) return 0; 
 

     // Find the correct line, beginning with "VmPeak:": 
     int peak_kb = 0; 
     while (!feof(in) && fscanf(in, "VmPeak: %d kB", &peak_kb) != 1) 
         while (!feof(in) && fgetc(in) != '\n') 
             ; 
     fclose(in); 
 

     return peak_kb; 
 } 
 

double memUsedPeak() {  
    double peak = memReadPeak() / (double)1024; 
 return peak;
}
インクメンタルにSleep時間を増やして、メモリ取得量の変化をみます。AWS CLIで、Lambdaの起動をかけています。(AWS SC3ユーザでもこの方法はできません) 結果がJsonで返ってきてピークメモリをログしています。

メモリ取得が最初の状態に戻ったときが、インスタンス再起動されたと推測できます。この結果では、700sec後に起動したときに、メモリがほぼ初期値に戻っているので、プロセス再起動(ColdStart)はされた、と考えられます。(別なインスタンスの新規起動かもしれない可能性は残ります。)
 
 
Invoke AWS after sleep(i)
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "455.812500MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):73177[ms]
0sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "633.902344MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70138[ms]
60sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "766.136719MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70010[ms]
120sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "898.433594MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70021[ms]
180sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1030.652344MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69835[ms]
240sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1153.636719MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69957[ms]
300sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1276.550781MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69994[ms]
360sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1399.472656MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70917[ms]
420sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1531.652344MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70442[ms]
480sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1663.828125MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69519[ms]
540sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1796.054688MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):69959[ms]
600sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "1919.246094MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70013[ms]
700sec
Calling lambda..SC3_Lambda_Engine 最小回数8回正循環.json clientConfig.requestTimeoutMs=900000sec
1:{
2:      "peak_memory":  "489.402344MB",
3:      "key2": "value2",
4:      "key3": "value3"
5:}
Elapsed time(C++):70774[ms]
800sec 
 

2020年5月14日木曜日

動き始めたAWS

ようやくクラウドが動きました。コードのLinux化に続く難所は越えたと思います。

嵌った点は、次の2点でした。

1)SDK使用時、DefaultTimeoutを超えると同期リクエストでもリトライする。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/lambda-function-retry-timeout-sdk/

非同期は、リトライが入るのは理解できますが、同期リクエストでもリトライがDefaultでは入ります。
確かに書いてありますが、C++ については、aws-sdk-docにもそのような記述例はなく、設定方法が不明です。海外を含めてこの点を指摘している記事はないと思います。

Lambdaリソース側では、メモリ3GB、15分のタイムアウトを設定しています。それとは別にCallerがタイムアウトを設定してやらないといけません。そうしないと、C++の場合、defaultでは、10秒くらいで、タイムアウトリトライが発生するようです。リソース側の設定と同じ、15分に設定しました。

Aws::Client::ClientConfiguration clientConfig;
     clientConfig.requestTimeoutMs = 15*60*1000;



2)Pythonライブラリの配置
クラウドにアップするときに、ZIPで固めます。これは、CMAKEがやってくれます。ただし、Pythonについては、コアについてはやってくれますが、Python上のソースについてはやってくれません。この辺、どこに配置されるかが判らず、以下のようなエラーが発生しました。

Could not find platform independent libraries <prefix>
Could not find platform dependent libraries <exec_prefix>
Consider setting $PYTHONHOME to <prefix>[:<exec_prefix>]

これについては、以下でDirectoryを出力させてどこに配置されるのかを調べました。
  std::system("ls -l ");

で、上で調べたDirectoryを環境変数PYTHONHOMEに設定して事なきを得ました。

2020年5月13日水曜日

WSL2に移行しました。

ubantu20.04 WSL1をWSL2にアップグレードしようとしましが、1日たっても終わらず断念しました。

なので、新しくubantu18.04をインストールし、それをWSL2にアップグレードしました。

AWSのミドルウェア、以下をインストールしました。

■aws CLI
■aws_lambda_cpp
■aws_sdk_cpp
■Docker Desktop WLS2



2020年5月12日火曜日

Excelへの解出力操作方法のビデオ

作成しました。

https://www.nurse-scheduling-software.com/publications/video/formatted_excel_output.AVI

スケジュールナース上の予定です。

Excel上のフォーマット出力です。スタッフ名は、記載順に出力されます。
スケジュールナース管理スタッフでない場合は、無視されます。
上のハードスケジュール予定は、赤で示されます。(これは、手直しをする場合に、手直し禁止の意味があるそうです。ある看護師長さんのご要望を実装しました。)

下は、通常出力になります。
上は勤怠管理用で最終リリース版、下は、解チェック用として利用されたらよいと思います。

2020年5月11日月曜日

WSL2に移行

デプロイしてみたのですが、動きませんでした。原因は色々ありそうですが、先は長そうです。
sleep問題もあるので、開発環境を一新することにしました。

最初からこちらを見ていればよかったのです。

https://qiita.com/mmns/items/eaf42dd3345a2285ff9e

WL2へは、
https://www.kkaneko.jp/tools/wsl/wsl2.html

https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel

を参照しました。開発ツールのインストールにまる一日かかります。

2020年5月10日日曜日

dynamodb get_item (C++) 組み込み

SDKサンプルをいじって、get_itemルーチンを以下のように記述しました。 これを使って、dynamodbをポーリングします。ItemのAttribute Interruptが"On" になっていたら求解を停止します。
■Interrupt   
    On/Off
 


string get_item(string table_name,string item_name,string attribute_name)
  {
        const Aws::String table=table_name;//(argv[1]);
        const Aws::String name=item_name;//(argv[2]);
        const Aws::String projection="";//(argc > 3 ? argv[3] : "");

        // snippet-start:[dynamodb.cpp.get_item.code]
        Aws::Client::ClientConfiguration clientConfig;
        Aws::DynamoDB::DynamoDBClient dynamoClient(clientConfig);
        Aws::DynamoDB::Model::GetItemRequest req;

        // Set up the request
        req.SetTableName(table);
        Aws::DynamoDB::Model::AttributeValue hashKey;
        hashKey.SetS(name);
        req.AddKey("Name", hashKey);
        if (!projection.empty())
            req.SetProjectionExpression(projection);

        // Retrieve the item's fields and values
        const Aws::DynamoDB::Model::GetItemOutcome& result = dynamoClient.GetItem(req);
        if (result.IsSuccess())
        {
            // Reference the retrieved fields/values
            const Aws::Map& item = result.GetResult().GetItem();
            if (item.size() > 0)
            {
                // Output each retrieved field and its value
                for (const auto& i : item){
     if (i.first==trim(attribute_name)){
      return i.second.GetS();
     }
                    std::cout << i.first << ": " << i.second.GetS() << std::endl;
                }    
            }
            else
            {
                std::cout << "No item found with the key " << name << std::endl;
            }

        }
        else
        {
            std::cout << "Failed to get item: " << result.GetError().GetMessage();
        }
        return "";
        // snippet-end:[dynamodb.cpp.get_item.code]
    }

2020年5月9日土曜日

dynamodb update_item (C++)を組み込み

SDKサンプルをいじって、update_itemルーチンを以下のように記述しました。 これを使って、今までファイル出力していた次をdynamodb上にそれぞれのattribute_nameで出力します。

■property.py   
     Python コード
■solution1.txt       
     シフト解
■solution1_task.txt
     タスク解
■Status    
     GUI出力
     
bool update_item(string table_name,string item_name,string attribute_name, string &description)
{
        const Aws::String tableName=table_name;//(argv[1]);
        const Aws::String keyValue=item_name;//(argv[2]);
        const Aws::String attributeNameAndValue=attribute_name;//(argv[3]);

        // snippet-start:[dynamodb.cpp.update_item.code]
        Aws::Client::ClientConfiguration clientConfig;
        Aws::DynamoDB::DynamoDBClient dynamoClient(clientConfig);

        // *** Define UpdateItem request arguments
        // Define TableName argument
        Aws::DynamoDB::Model::UpdateItemRequest request;
        request.SetTableName(tableName);

        // Define KeyName argument
        Aws::DynamoDB::Model::AttributeValue attribValue;
        attribValue.SetS(keyValue);
        request.AddKey("Name", attribValue);

        // Construct the SET update expression argument
        Aws::String update_expression("SET #a = :valueA");
        request.SetUpdateExpression(update_expression);

        // Parse the attribute name and value. Syntax: "name=value"
        //auto parsed = Aws::Utils::StringUtils::Split(attributeNameAndValue, '=');
        // parsed[0] == attribute name, parsed[1] == attribute value
        //if (parsed.size() != 2)
        //{
        //    std::cout << "Invalid argument syntax: " << attributeNameAndValue << USAGE;
        //    return 1;
        //}

        // Construct attribute name argument
        // Note: Setting the ExpressionAttributeNames argument is required only
        // when the name is a reserved word, such as "default". Otherwise, the 
        // name can be included in the update_expression, as in 
        // "SET MyAttributeName = :valueA"
        Aws::Map expressionAttributeNames;
        expressionAttributeNames["#a"] = attribute_name;//parsed[0];
        request.SetExpressionAttributeNames(expressionAttributeNames);

        // Construct attribute value argument
        Aws::DynamoDB::Model::AttributeValue attributeUpdatedValue;
        attributeUpdatedValue.SetS(description);//parsed[1]);
        Aws::Map expressionAttributeValues;
        expressionAttributeValues[":valueA"] = attributeUpdatedValue;
        request.SetExpressionAttributeValues(expressionAttributeValues);

        // Update the item
        const Aws::DynamoDB::Model::UpdateItemOutcome& result = dynamoClient.UpdateItem(request);
        if (!result.IsSuccess())
        {
            std::cout << result.GetError().GetMessage() << std::endl;
            return false;
        }
        std::cout << "Item was updated" << std::endl;
        return true;
        // snippet-end:[dynamodb.cpp.update_item.code]
    }

2020年5月8日金曜日

dynamodbの使い方(C++)

aws-doc-sdk-examplesをコンパイルして、サンプルで使い方を学びました。(ubuntu20.04 WSL上でコンパイル)

コマンドは、delete_table,create_table,put_item,get_item,update_itemになります。注意すべきは、put_itemです。全てのattributeが置き換えられます。部分的なattributeに対する更新は、update_itemを使う、ということが分かりました。

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ls
CMakeCache.txt  batch_get_item       create_table_composite_key  describe_table  put_item
CMakeFiles      cmake_install.cmake  delete_item                 get_item        update_item
Makefile        create_table         delete_table                list_tables     update_table

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./list_tables
Your DynamoDB Tables:
HelloTable
mywebsocket_connections
simple-websockets-app-py-connections

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./delete_table HelloTable
Table "HelloTable deleted!
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./list_tables

Your DynamoDB Tables:
mywebsocket_connections
simple-websockets-app-py-connections

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./create_table HelloTable us-east-1
Creating table HelloTable with a simple primary key: "Name"
Table "HelloTable created!

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./list_tables
Your DynamoDB Tables:
HelloTable
mywebsocket_connections
simple-websockets-app-py-connections

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./put_item HelloTable sugawara Height=172 Weight=85
Done!
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./get_item HelloTable sugawara
Height: 172
Name: sugawara
Weight: 85
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./put_item HelloTable sugawara Height=172
Done!
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./get_item HelloTable sugawara
Height: 172
Name: sugawara

tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./put_item HelloTable sugawara Height=172 Weight=85
Done!
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./get_item HelloTable sugawara
Height: 172
Name: sugawara
Weight: 85
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./update_item HelloTable sugawara Height=173
Item was updated
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$ ./get_item HelloTable sugawara
Height: 173
Name: sugawara
Weight: 85
tak@win10-64:~/aws-doc-sdk-examples/cpp/example_code/dynamodb/build$

2020年5月7日木曜日

AWSの構成2

構成を上のように替えました。

1)AWS上のSC3 Userは、菅原システムズアカウントにあるSC3 Lambda FunctionをCALLします。
2)CALL時のPayloadには、problem.jsonを載せます。
3)SC3 Lambda Functionは、求解状況をSC3UserアカウントにあるDynamoDBに書き込みます。
4)SC3 Userは、求解を途中で停止したいときは、DynamoDBに書き込みます。
5)SC3 Lambda Engineは、User Interrupt書き込みをポーリングし、停止要求と判断したら、求解を停止し、それまでのBest解をDynamoDBに書き込み終了します。
6)解が求まったら、解をDyanamoDBに書き込み終了します。

ここで、リソースは、

LambdaFunction:菅原システムズ側
DynamoDB:お客さま側

にあるので、それぞれの側で、アクセス許可が必要となります。AWS内でCloseし、外部からは
アクセスできないので、セキュリティ上も好ましいものとなります。お客さまが、AWS内でアプリを組む場合には、最適な構成ではないかと思います。

2020年5月4日月曜日

Visual C++ からLinuxへの移植

作業を開始しました。移植作業だけで1週間かかります。
以下に作業をまとめます。
項目WindowsLinux対応
ファイル名大文字小文字区別なし区別ありファイル名を統一
ファイル名ShiftJisUtf-8日本語コメントでパースできないのでUTF-8に統一
プロジェクトファイルsln/vscprojファイルCmakelists.txtCmakelists.txt作成
DBL_MAX #include<cfloat> 
#include file pathName\SubNameName/SubName 
関数popcnt/bitscanforward http://herumi.in.coocan.jp/prog/gcc-and-vc.html
Link 順序 Link順序管理必要 

2020年5月3日日曜日

VS2019 へ移行

今まで、VS2017を使ってきたのですが、コードの整理を含めてVS2019に移行中です。

VS2019にコンパイラを替えただけなのに、結構な量のコンパイルエラーが起きます。コンパイラの解釈が変わったことによることが原因です。使い続けて20年位になりますが、今だにそういう状態です。コンパイラのバグFixもありますが、C++の言語仕様が、今だに進化していることが 関わっているようにも思えます。 進化により、主に高級言語化傾向があり、より少ない行数でやりたいことが書けるようになってきています。(今回、C++17にしたかったのですが、default C++14、 部分的にC++17です。)

もう一つの目的は、クロスプラットフォーム化にあります。今までは、Windowsだけを考えればよかったのですが、AWS対応のためには、クロスプラットフォームプロジェクト化は、必須です。ただ、前に述べたように、AWSのエンジンは、かなりいじる必要があり、単純にクロスプラットフォーム化すれば済むという話ではなく、AWS用のコードをかなり書かないといけません。この辺は、AWS-SDKのコードを参考にしながら書くことになります。

2020年5月2日土曜日

AWS 構成を変更

Is it possible to kill/stop a running lambda function?

 1)You cannot kill a running lambda function. Though there is another way by which you can set concurrency limit to 0. This will stop it from starting any more executions.
$ aws lambda put-function-concurrency --function-name my-function --reserved-concurrent-executions 0

これだと、全てのインスタンスで止まってしまいます。緊急停止用途と理解します。

2)That's not what we should use lambda for

Ideally each lambda function should be only one function. A real one function of the programming language. Which not loop or even have state. And it should be able to run in parallel. This is functional paradigm

If you need to have state, use step function to call lambda. Even you just need to loop for pulling task but if it can take times longer than 1 minute you should use step function. All lambda function should be able to let itself die in 1 minute and so you could maintain that it will have only one of it alive in each minute

If you really need to ensure that it must have only one of it in each minute. You could use dynamodb or any other state keeper as a mutex, to let every lambda check that should it end itself when the mutex id was changed. Not that it will always have one lambda but it let old lambda kill itself when it know it not needed

なるほど、lambdaは、Stateレスが前提なのですね。
現状のエンジンをそのままLambda化するのは、難しそうだということが理解できました。

STEP FUNCTIONを使って、API化することは技術的には可能でしょうが、そのための開発負荷が半端ではなくなってしまいます。オーバヘッドも無視できないですし、本筋以外での課金は、避けたいです。

そこで、APIGateWayを通さずに直接に、直接にユーザがLambdaを呼ぶ方法に改めたいと思います。当然のことながら、顧客もAWSアカウントを持つ必要がありますが、元々持っているならば障害にはなりません。

2020年5月1日金曜日

はじめてのAWS LAMBDA CPPサンプル

https://aws.amazon.com/jp/blogs/compute/introducing-the-c-lambda-runtime/
に従ってサンプルを動かしてみました。

■必要となるライブラリのインストール
cmake/g++/libcur..等、次々に文句を言ってきますが、言ってきた時点で、ubuntu用のライブラリインストールの仕方を検索インストールを行いました。

■aws-sdk-cppのmake
失敗しました。同じ関数を2回アクセスしているところ、2回目は、betterAccessKeyを期待しているようですが、goodAccessKeyが却っているようでした。原因は分かりません。とりあえず、コメントアウトして無理やりmakeを通しました。→ubuntu20.04 WSL1にsleepが効かない問題があるようです。色々パッチを充てる必要がありそうです

TEST(InstanceProfileCredentialsProviderTest, TestThatProviderRefreshes)

{

    auto mockClient = Aws::MakeShared(AllocationTag);

    const char* validCredentials = "{ \"AccessKeyId\": \"goodAccessKey\", \"SecretAccessKey\": \"goodSecretKey\", \"Token\": \"goodToken\" }";

    mockClient->SetMockedCredentialsValue(validCredentials);

    InstanceProfileCredentialsProvider provider(Aws::MakeShared(AllocationTag, mockClient), 10);

    ASSERT_EQ("goodAccessKey", provider.GetAWSCredentials().GetAWSAccessKeyId());

    ASSERT_EQ("goodSecretKey", provider.GetAWSCredentials().GetAWSSecretKey());

    const char* nextSetOfCredentials = "{ \"AccessKeyId\": \"betterAccessKey\", \"SecretAccessKey\": \"betterSecretKey\", \"Token\": \"betterToken\" }";

    mockClient->SetMockedCredentialsValue(nextSetOfCredentials);

    std::this_thread::sleep_for(std::chrono::milliseconds(100));

 

    //ASSERT_EQ("betterAccessKey", provider.GetAWSCredentials().GetAWSAccessKeyId());

    //ASSERT_EQ("betterSecretKey", provider.GetAWSCredentials().GetAWSSecretKey());

}

■LAMBDAの登録がタイムアウト
次のコマンドで登録しようとしたのですが、タイムアウトで切断されてしまいました。
10MB以上は、S3経由で、アップロードすることが推奨されているようでしたので、S3で作ったバケットに置いたのですが、CLIでは、上手く呼び出すことができませんでした。なので、WEBコンソールで、関数の作成を行いアップロード、ロールの指定を行いました。

 aws lambda create-function \
--function-name encode-file \
--role <specify the same role arn used in the prior Lambda> \
--runtime provided \
--timeout 15 \
--memory-size 128 \
--handler encoder \
--zip-file fileb://encoder.zip

 ■CLIで起動
$ aws lambda invoke --function-name encode-file --payload '{"s3bucket": "your_bucket_name", "s3key":"your_file_key" }' base64_image.txt
で、base64_image.txtが出来ることを確認しました。中身のテキストをネット上のbase64decoderに通すと、S3バケットに置いたファイルの中身が再現していることを確認しました。

■まとめ
とりあえず、C++でLambdaFunctionをコンソール上から呼び出すことができました。
必要なライブラリ、aws-lambda-cpp,aws-sdk-cppを使いこなすことで、AWS上での操作が出来るようです。