骨伝導イヤホン買った
いくつかの骨伝導イヤホンを比較検討して、AVIOT Openpiece Elite を購入しました。
今回主に比較したイヤホンは次のものになります。
- Shokz OpenRun 無印 (+Mini)
- Shokz OpenRun Pro (+Mini)
- AVIOT Openpiece Playful
- AVIOT Openpiece Elite
- HAYLOU PurFree BC01
- audio-technica ATH-CC500BT
比較結果
感覚的な部分については1~5の5段階評価しています。主観的な評価となりますが、ご了承ください。
製品名 | 音質 *1 | 着け心地 | 音漏れ | デザイン | 防塵/防水 | 価格 | コーデック | 備考 |
---|---|---|---|---|---|---|---|---|
Shokz OpenRun | 2 | 2 | 4 | 3 | IP67 | SBC | 17880 | 骨伝導といえばのブランド。 ちょっと大きめ |
Shokz OpenRun Mini | 2 | 4 | 4 | 3 | IP67 | SBC | 17880 | 頭が大きいつもりだったが、普通に装着できた。 |
Shokz OpenRun Pro | 4 | 2 | 4 | 3 | IP55 | SBC | 23880 | これならOpen Run無印でいいかなという印象 |
Shokz OpenRun Pro Mini | 4 | 4 | 4 | 3 | IP55 | SBC | 23880 | 頭が大きいつもりだったが、普通に装着できた。 |
AVIOT Openpiece Playful | 4 | 1 | 3 | 4 | IP67 | AAC/SBC | 15950 | 試着は絶対にすべき |
AVIOT Openpiece Elite | 5 | 1 | 3 | 5 | IPX5 | AAC/SBC | 23870 (ブームマイク付き) |
音質マイク共に素晴らしい! 試着は絶対にすべき ブームマイク無しのマイク音質は微妙 |
HAYLOU PurFree BC01 | 1 *2 | 5 | 2 | 2 | IP67 | aptX/SBC | 12900 | 着け心地最高! 最後まで迷った。 |
audio-technica ATH-CC500BT | 4 | 2 | 3 | 3 | IPX4 | aptX HD/aptX/ AAC/SBT |
17600 | アプリが良さげだった。 防水性能もう少し欲しい |
まとめ
- 2023/10 現在これ選んでおけばいいというのはないなーという印象。
- Openpiece は耳にフィットすれば、かなりいい感じ
- 音漏れは HAYLOU PurFree BC01 以外はほぼ気にならかなった。満員電車とかではさすがに気になるだろうけれど
- 絶対試着すべき。
電子書籍/紙書籍の技術書をどのように選択して購入すべきか
はじめに
電子書籍/紙書籍の技術書のどちらを選択して購入すべきかの私見をまとめた記事となります。
電子書籍/紙書籍の技術書の選定基準
電子書籍と紙書籍のどちらを選択して購入すべきかを考える際に、私が考える主なポイントは次の通りです。
- 購入する電子書籍のフォーマット
- 読みたい場所。外で読む場合、紙書籍は不便なため、電子書籍を選択します。
基本的には、後述する電子書籍のフォーマットによって、購入する書籍の形式を決定します。
また、索引や目次などの参照が必要な場合や速読に近い読み方をする書籍などは、電子書籍購入後に紙書籍を購入することが多いです。
購入する書籍の形式
電子書籍のフォーマットは、主に以下の 3 つがあります。
- EPUB
こちらのフォーマットは、一般的にはリフロー型のフォーマットです。
基本的には DRM フリーとなります。1 - PDF
こちらのフォーマットは、一般的には固定型のフォーマットです。
基本的には DRM フリーとなります。2 - 電子書籍ストア専用フォーマット
Amazon Kindle などの総合電子書籍ストアで販売されている電子書籍専用のフォーマットです。リフロー型と固定型の両方があります。
電子書籍ストア専用フォーマットは、原則 DRM がかかっています。
電子書籍を購入する場合、基本的には私は EPUB
, Kindle (リフロー型)
, 紙書籍
の優先順位で購入するようにしています。
PDF
や Kindle
の固定レイアウトは、PC やスマホなど電子機器で読むことに特化されていることが少なく、読みにくいことが多いためほぼ購入しません。これらを購入するのは、主に 2 つあり、外で読みたい書籍または、絶版の書籍など他のフォーマットで購入できない場合のみとなります。
固定型とリフロー型について
日本電子出版協会のサイトからそれぞれの説明を引用させていただきます。
リフロー型電子書籍とは、表示するデバイスの画面サイズや文字サイズの変更などに合わせて、テキストやレイアウトが流動的に表示される方法で制作された電子書籍である。フォントを拡大したり縮小すると、1行の文字数が自動的に変更されて再表示されるため、紙の書籍のようなページの概念を持たない(ただしページ機能を持たせることは仕組みとして可能)。
https://www.jepa.or.jp/ebookpedia/201508_2551/
フィックス型電子書籍とは、表示するデバイスの画面サイズに関わらず、印刷された本と同じように文字や図表などのレイアウトが固定される方式で制作された電子書籍をいう。非リフロー型、固定レイアウト型などとも呼ばれる。
https://www.jepa.or.jp/ebookpedia/201508_2553/
EPUB が購入できる電子書籍ストア
EPUB
は Amazon などの総合的な電子書籍ストアでは購入できないため、一般的には各出版社の電子書籍ストアで購入することになります。
私が良く購入する出版社ごとの電子書籍ストアは次のような傾向があります。
- 技術評論社 (Gihyo Digital Publishing)
最近の書籍はほぼ
EPUB
が購入できます。 - O'Reilly Japan (O'Reilly Japan Ebook Store)
最近の書籍はほぼ
EPUB
が購入できます。 - インプレス (インプレスブックス)
ほぼ
PDF
のみですが、まれにEPUB
もあります。 - 翔泳社
私の知る限り、
EPUB
は存在しません。Kindle
ではリフロー型のレイアウトの事が多いので、そちらを購入します。 - その他
その他の出版社の電子書籍ストアは、基本的には
PDF
または、電子書籍ストア専用フォーマットのみのことが多いです。リフロー型レイアウトはほぼ存在しないため、紙書籍を購入することが多いです。
sudo -i と sudo su -の違い
どちらもrootユーザーに昇格することができるがこれらの違いが気になったので調査結果をメモ。
まず、これらのコマンドがどういう意味であるかを調べた。
sudo
: Super User DOsu
: Substitute User
sudo
-i
オプションの意味は simulate initial loginであるようだ。
違い1: 実行されるプロセス数が違う
当然だが、sudo su -
はsudo
とsu
コマンドを実行する。rootに昇格している間はこれらのプロセスが立ち上がったままとなる。
対してsudo -i
コマンドはsudo
コマンドのみを実行する。rootに昇格している間はsudo
プロセスのみとなる。
どちらも利用したことがあればわかるが、体感的な速度差はない。
リソースは以下のような結果となった。
sudo su -
昇格時
# pidstat -r -C su Linux 5.4.0-58-generic (ubuntu2004) 2020年12月21日 _x86_64_ (1 CPU) 15時26分13秒 UID PID minflt/s majflt/s VSZ RSS %MEM Command 15時26分13秒 0 5064 0.00 0.00 10280 4572 0.49 sudo 15時26分13秒 0 5065 0.00 0.00 9428 4292 0.46 su
$ time sudo su - -c : real 0m0.013s user 0m0.008s sys 0m0.003s
sudo -i
昇格時
~# pidstat -r -C su Linux 5.4.0-58-generic (ubuntu2004) 2020年12月21日 _x86_64_ (1 CPU) 15時31分08秒 UID PID minflt/s majflt/s VSZ RSS %MEM Command 15時31分08秒 0 6061 0.00 0.00 10364 4572 0.49 sudo
$ time sudo -i : real 0m0.009s user 0m0.006s sys 0m0.003s
リソース面だけでみれば、sudo
コマンドの結果はほぼ変わらず、su
コマンドが加わった分、sudo -i
ほうが有利なようだ。
違い2: 環境変数
sudo -i
の場合以下の環境変数がセットされている。
- SUDO_COMMAND: 実行コマンド
- SUDO_UID: 昇格前のUID
- SUDO_GID: 昇格前のGID
- SUDO_USER: 昇格前のUSER
CentOSの sudo -i
だと/usr/local/binがPATH環境変数がセットされていない。
CentOS7, CentOS8で動作を確認
$ sudo -i echo '$PATH' /usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin:/root/.dotnet/tools:/root/bin $ sudo su - -c 'echo $PATH' /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/.dotnet/tools:/root/bin
Ubuntu20.04ではPATH環境変数に /usr/local/binがセットされていることを確認。
これは/etc/sudoersのデフォルト設定による違いとなる。
CentOS8
$ sudo grep secure_path /etc/sudoers Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin
Ubuntu20.04
$ sudo grep secure_path /etc/sudoers Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin"
su
コマンドでPATH環境変数は su
コマンドがデフォルトでセットしているようだ。
ENV_SUPATH (string) Defines the PATH environment variable for root. The default value is /usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin.
環境変数の引継ぎ
sudo -i
では環境変数が引き継がれる
$ sudo -i date 2020年 12月 21日 月曜日 19:37:30 JST $ LANG=C sudo -i date Mon Dec 21 19:37:36 JST 2020
sudo su -
では環境変数が引き継がれない
$ sudo su - -c date 2020年 12月 21日 月曜日 19:38:54 JST $ LANG=C sudo su - -c date 2020年 12月 21日 月曜日 19:39:44 JST
昇格後に環境変数をセットすれば対応可能
$ sudo su - -c 'LANG=C date' Mon Dec 21 19:40:06 JST 2020
これは一長一短だと思う。個人的には引き継ないsudo su -
のほうが自然な動作に感じる。
まとめ
違い | sudo -i | sudo su - |
---|---|---|
プロセス | sudo のみ実行 | sudo, suを実行 |
デフォルト環境変数 | /etc/sudoersのsecure_path (ディストリビューションによってデフォルト値が異なる) |
/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin |
環境変数の引継ぎ | 引き継ぐ | 引き継がない |
各種リソース面では sudo -i
が有利、環境変数関連は sudo su -
のほうが好み(ディストリビューションの違いを意識しなくてよい)
用途によって使い分けるとよさそう。
参考情報
The Differences between Su, Sudo Su, Sudo -s and Sudo -i
linux - What is the difference between sudo -i and sudo su - - Server Fault
Rustのmockallクレートを利用してみた。
Rustでモッククレートはいくつかあるが、一番良さそうであったmockallクレートを利用してみた。
https://crates.io/crates/mockall
今回確認した各種バージョン情報
名称 | バージョン |
---|---|
Windows10 Pro | 1909 |
Rust | 1.47.0 |
mockall | 0.8.3 |
automockアトリビュートが何をしているのかわからないので、Usageにあるトレイトをcargo expandしてみる
#[cfg(test)] use mockall::{automock, mock, predicate::*}; #[cfg_attr(test, automock)] trait MyTrait { fn foo(&self, x: u32) -> u32; }
cargo expand --lib --tests
結果
#[cfg(test)] use mockall::{automock, mock, predicate::*}; trait MyTrait { fn foo(&self, x: u32) -> u32; } #[allow(non_snake_case)] #[allow(missing_docs)] pub mod __mock_MockMyTrait { use super::*; } #[allow(non_camel_case_types)] #[allow(non_snake_case)] #[allow(missing_docs)] struct MockMyTrait { MyTrait_expectations: MockMyTrait_MyTrait, } impl ::std::default::Default for MockMyTrait { #[allow(clippy::default_trait_access)] fn default() -> Self { Self { MyTrait_expectations: Default::default(), } } } #[allow(non_snake_case)] #[allow(missing_docs)] pub mod __mock_MockMyTrait_MyTrait { // 長いので省略 } #[allow(non_camel_case_types)] #[allow(non_snake_case)] #[allow(missing_docs)] struct MockMyTrait_MyTrait { foo: __mock_MockMyTrait_MyTrait::__foo::Expectations, } impl ::std::default::Default for MockMyTrait_MyTrait { fn default() -> Self { Self { foo: Default::default(), } } } impl MockMyTrait_MyTrait { /// Validate that all current expectations for all methods have /// been satisfied, and discard them. pub fn checkpoint(&mut self) { { self.foo.checkpoint(); } } } impl MockMyTrait { /// Validate that all current expectations for all methods have /// been satisfied, and discard them. pub fn checkpoint(&mut self) { self.MyTrait_expectations.checkpoint(); } /// Create a new mock object with no expectations. /// /// This method will not be generated if the real struct /// already has a `new` method. However, it *will* be /// generated if the struct implements a trait with a `new` /// method. The trait's `new` method can still be called /// like `<MockX as TraitY>::new` pub fn new() -> Self { Self::default() } } impl MyTrait for MockMyTrait { fn foo(&self, x: u32) -> u32 { self.MyTrait_expectations .foo .call(x) .expect("MockMyTrait::foo: No matching expectation found") } } impl MockMyTrait { #[must_use = "Must set return value when not using the \"nightly\" feature"] ///Create an [`Expectation`](__mock_MockMyTrait_MyTrait/__foo/struct.Expectation.html) for mocking the `foo` method fn expect_foo(&mut self) -> &mut __mock_MockMyTrait_MyTrait::__foo::Expectation { self.MyTrait_expectations.foo.expect() } }
トレイト名に接頭辞Mockを付けた構造体とそれに加えて接尾辞__トレイト名
の構造体を実装するようだ。
トレイトメソッドはexpect_メソッド名
のメソッドが実装されこれがモックメソッドになるようだ。
基本的には、複数の実装(impl)をする場合は、mockマクロを使い、一つだけの実装であれば、automock属性を使うのが良さそう。
reqwest利用箇所をモック化してみた。
基本的にはautomockアトリビュートかmockマクロを使うだけで非常に簡単に実装できる。
AWS ソリューションアーキテクト アソシエイト合格した。
AWS ソリューションアーキテクトアソシエイト(SAA-C02)合格した。
7月くらいから勉強を始めて、10月に取得。
スコアは 822
事前知識
AWSの業務経験は主業務でない時期も含めて2年程度。インフラ・アプリケーションどちらもそこそこやる。
主に利用したことのあるサービスとしては VPC, EC2, S3, CloudWatch, Lambda, IAM, EFS, RDSなど。
学習
学習教材としては、以下を利用
SAA-C02には対応していないが、主要なサービスは掲載されていたように思う。 本書に載っていない問題で出題されたサービスもいくつか存在した。
問題集としてUdemyの以下を利用
1週目は50~70点ほどであったが、間違えた問題やよくわからない問題の解説を熟読して、 2週目は90点程度になった。
Udemyの問題集にはあり、AWS認定資格試験テキスト AWS認定 ソリューションアーキテクト-アソシエイトには掲載されていないサービス例として以下のものが存在した。*1
- Amazon FSx
- Active Directory Connector
- Simple Active Directory
- AWS Organizations
- AWS Transit Gateway
- AWS Snowball
- Amazon Athena
本番より難しいと感じる問題がいくつもあったが回答の解説が丁寧に記載してあるものが多いため、勉強になった。
*1:Athenaと Snowballは名前だけは存在する
Node.jsのN-APIをRustから使ってみた。
Node.jsにてRustのプログラムをffiしたいと思い、node-ffiを調べてみたが、しばらく更新されておらず、Node.js 12以降だと利用できない模様。
GitHub - node-ffi/node-ffi: Node.js Foreign Function Interface
RPCではない方法で他に連携する方法はないかと調べてみた結果Node.jsにはネイティブアドオンを作成するためのAPIが用意されているらしい。
今回はこれをRustから利用できる形で提供してくれているnapi-rsを使用してみる。
今回検証する環境の各バージョン
- Windows 10 1909
- Node.js v14.15.0
- napi-rs 0.3.9
- Rust 1.47.0
- napi 0.5.1
- napi-derive 0.5.1
- napi-build 0.2.1
napi-rsのドキュメントに従いcargo buildしてみたところ以下のエラーが発生
thread 'main' panicked at 'Unable to find libclang: "couldn\'t find any valid shared libraries matching: [\'clang.dll\', \'libclang.dll\'], set the
LIBCLANG_PATH
environment variable to a path where one of these files can be found (invalid: [])"'
clangが必要なようのでLLVMをインストール
今回インストールしたバージョンは11.0.0
The LLVM Compiler Infrastructure Project
他は特に問題なくcargo buildすることができた。
Node.jsからRustのfibonacci関数を呼び出すサンプル
Node.jsとRustのfibonacci関数を比較
PASS ./fib.test.js (14.479 s) √ fibonacci(30) for rust (3 ms) √ fibonacci(30) for js (16 ms) √ fibonacci(31) for rust (2 ms) √ fibonacci(31) for js (24 ms) √ fibonacci(32) for rust (3 ms) √ fibonacci(32) for js (39 ms) √ fibonacci(33) for rust (5 ms) √ fibonacci(33) for js (64 ms) √ fibonacci(34) for rust (13 ms) √ fibonacci(34) for js (102 ms) √ fibonacci(35) for rust (15 ms) √ fibonacci(35) for js (168 ms) √ fibonacci(36) for rust (26 ms) √ fibonacci(36) for js (263 ms) √ fibonacci(37) for rust (47 ms) √ fibonacci(37) for js (432 ms) √ fibonacci(38) for rust (68 ms) √ fibonacci(38) for js (701 ms) √ fibonacci(39) for rust (108 ms) √ fibonacci(39) for js (1119 ms) √ fibonacci(40) for rust (168 ms) √ fibonacci(40) for js (1828 ms) √ fibonacci(41) for rust (294 ms) √ fibonacci(41) for js (3061 ms) √ fibonacci(42) for rust (474 ms) √ fibonacci(42) for js (4855 ms)
Rust版のほうが概ね10倍程度は高速なようだ。 fibonacci関数は本来キャッシュすべきとか、Rust版は末尾再帰最適化がかかっているとかはあるがnapi-rsの検証が目的なのでパフォーマンスは次回以降にちゃんと検証したい。
WindowsでRustのDieselライブラリを利用
TLDR
開発用途であればWSLを使うほうが楽。
本番用途でも静的リンクは大変。
Dieselとは
RustのORM/クエリビルダライブラリ
PostgreSQL, MySQL, SQLite3に対応しているが、それぞれのSQLクライアントライブラリにリンクする必要がある。
後述するが、それぞれのクライアントに限定してインストールすることもできる。
Vcpkg
VpkgはC言語とC++のライブラリ管理ツール
今回はVcpkgを利用して各種SQLクライアントのライブラリインストールしてみる。Vcpkgのインストール方法については下記ページを参照。
特筆すべき事項としては、Visual Studioの英語の言語パックのインストールが必要。
静的リンク
以下で全てのインストールはできそうだが7/26現在MySQL, PostgreSQLの静的リンクはできなかった。
#!pwsh cd $env:VCPKG_ROOT .\vcpkg.exe --triplet x64-windows-static install libpq .\vcpkg.exe --triplet x64-windows-static install libmysql .\vcpkg.exe --triplet x64-windows-static install sqlite3 $env:RUSTFLAGS= "-Ctarget-feature=+crt-static" cargo install diesel_cli
PostgreSQL(静的リンク)
2020/07/26 インストール失敗
#!pwsh cd $env:VCPKG_ROOT .\vcpkg.exe --triplet x64-windows-static install libpq $env:RUSTFLAGS= "-Ctarget-feature=+crt-static" cargo install diesel_cli --no-default_features --features postgres
MySQL(静的リンク)
2020/07/26 インストール失敗
#!pwsh cd $env:VCPKG_ROOT .\vcpkg.exe --triplet x64-windows-static install libmysql $env:RUSTFLAGS= "-Ctarget-feature=+crt-static" cargo install diesel_cli --no-default_features --features mysql
SQLite(静的リンク)
#!pwsh cd $env:VCPKG_ROOT .\vcpkg.exe --triplet x64-windows-static install sqlite3 $env:RUSTFLAGS= "-Ctarget-feature=+crt-static" cargo install diesel_cli --no-default_features --features sqlite
動的リンク
#!pwsh cd $env:VCPKG_ROOT .\vcpkg.exe --triplet x64-windows install libpq .\vcpkg.exe --triplet x64-windows install libmysql .\vcpkg.exe --triplet x64-windows install sqlite3 # 動的リンクする場合は VCPKGRS_DYNAMICに値を設定する。 (参考: https://docs.rs/vcpkg/) $env:VCPKGRS_DYNAMIC = 1 cargo install diesel_cli
動的リンクは可能だが、当然DLLのパスを通す必要がある。通常は %VCPKG_ROOT%\installed\x64-windows\bin
あたり。汎用DLLも存在するためDLL Hellが起きないか不安だ。
WSL1 (Ubuntu 2004)
開発環境ならこれがもっとも簡単
ただし 2020/07/26現在WSL1のUbuntu2004ではrustupのインストールがうまくいかない
環境変数に RUSTUP_IO_THREADS=1
に付与すればインストールできた。
#!bash export RUSTUP_IO_THREADS=1 curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh sudo apt install libpq-dev libmysqlclient-dev libsqlite3-dev cargo install diesel
Windowsからdieselを使うときは以下のように実行
#!pwsh wsl bash -lc 'diesel ...'