ま、そんなところで。

ニッチな技術系メモとか、車輪を再発明してみたりとか.

VirtualBox上のLinuxOSの動作がとても遅い場合に試す設定のメモ

VirtualBox上でLinuxOSを動作させる場合、動作が非常に遅くなるケースがあります.
このような場合に行う設定のメモ.

1. I/O スケジューラの変更

① udevルールを作成

/etc/udev/rules.d/50-ioschedulers.rules を作成.
(※ ruleの優先度を決めるファイル先頭の数値は必要に応じて適当な値にすること)

② ruleの設定

ruleの内容は以下のように設定すると、起動時にスケジューラをnoneに設定してくれる.

# i/o schedulerを仮想マシン用に"none"にする.
# ※ KERNEL==は物理ディスクデバイス. 以下設定では /dev/sda〜/dev/sdz を指す.
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}="0", ATTR{queue/scheduler}="none"

2. VirtiaoBox Guest Additionsをインストール

2-1. 前準備

GuestOS側で必要なソフトをインストールする

sudo apt install build-essential
# ※ non-LTSの場合.
sudo apt install linux-headers-generic 
# ※ LTSの場合. xx-yyはubuntuのLTSバージョン 20.04, 22.04.. etc
sudo apt install linux-headers-generic-hwe-{xx-yy}

2-2. Guest Additionsのインストール

①メディアを挿入する

guest additions CD の挿入

仮想マシン側で挿入された仮想ディスクをマウントする

# /mnt直下にdvd用のマウントポイントとなるディレクトリ作成
sudo mkdir -p /mnt/dvd
# Guest Additionsのディスクを/mnt/dvdへマウント
sudo mount /dev/dvd /mnt/dvd
/mnt/dvd: WARNING: device write-protected, mounted read-only.d

③ディスク内のVBoxLinuxAdditions.runを実行する

sudo /mnt/dvd/VBoxLinuxAdditions.run

仮想マシンを再起動

仮想マシンを再起動します.

sudo shutdown -r now

参考サイト

肥大化してしまったGitリポジトリのパフォーマンス低下を軽減するTIPS

開発プロジェクトが長いとリポジトリが肥大化しがちです.
大きくなったリポジトリではcloneやcheckoutのパフォーマンスが重く、ストレスを感じることが多いと思います.
そこで、大きくなってしまったリポジトリとうまく付き合っていくためのTipsをまとめてみました.

1. 最新履歴のみをcloneする(shallow-clone)

通常のcloneではリポジトリ内のすべての履歴を取得しますが、 CIツールなど、最新コミットや一部の履歴のみあれば十分な場合に shallow-clone を使用すると、ダウンロードするリポジトリデータのサイズを抑えることができます.

1-1. shallow-cloneを行う

shallow-cloneを行うには、clone時に以下のオプションを指定します.

# デフォルトブランチで、履歴N個分をclone
$ git clone [url] --depth N
# 指定したブランチで、履歴N個分をclone
$ git clone [url] --single-branch -b [ブランチ名] --depth N
# 全てのブランチについて、履歴N個分をclone
$ git clone [url] --no-single-branch --depth N

1-2. shallow-cloneされたブランチのupdate

shallow-cloneしたリポジトリのブランチをupdateするには、update-shallow オプションを指定します.
shallow-cloneで取得した起点コミット(grafted)以降の履歴のみを取得することができます.

# 指定ブランチについて現在のコミットより新しい履歴を取得
git fetch --update-shallow [remote名] [ブランチ名]

ブランチ名を省略することですべてのブランチについてshallow-clone起点コミット(grafted)以降の履歴を取得することもできます.
ただし、shallow-cloneが維持されるのは既存のブランチのみで、 ローカルに起点コミットがない(ex. リモートに新規ブランチがある)場合は、新規ブランチについてすべての履歴が取得されてしまいます.
これを防ぐには depth オプションを指定して、新規含むすべての最新コミットを起点コミットとして取得しなおします.

# すべてのブランチについて最新履歴のみ取得した状態にする
$ git fetch --update-shallow [--depth=N]

1-3. shallow-cloneの解除

shallow-cloneを解除するには、unshallow オプションをつけてfetchをおこないます.

$ git fetch --unshallow

2. 必要なオブジェクトのみをcloneする(partial-clone)

リポジトリをcloneする際に、Gitの履歴オブジェクトのうち、実データ(blob)やファイル構成(tree)に関する情報は、実際に必要になったタイミングで行うよう設定します.
遅延取得するデータの種類によってはgitの一部機能に制限がかかることがありますが、初回clone時にダウンロードするローカルリポジトリのデータサイズを抑えることができます.

前提として、bareリポジトリのあるサーバ側のgit設定として下記が必要になります.

# bareリポジトリ側にfilterを許可する設定
# ※ --globalをつけてサーバ側の実行ユーザに設定してもOK.
$ git config uploadpack.allowfilter true
$ git config uploadpack.allowanysha1inwant true

2-1. partial-cloneの種類

cloneから除外するオブジェクトの種類によって以下の2種類があります.

(1) tree-less clone

最新コミットと履歴のみを初回cloneで取得.

(2) blob-less clone

最新コミットと履歴のtreeを取得.

partiah-cloneについては、以下のサイトの解説がわかりやすいです.
github.blog

2-2. partial-cloneの操作

partial-cloneリポジトリは、以下のように設定します.

2-2-1. 新規にcloneするとき

# tree-less clone
$ git clone --fliter=tree:none [url] [clone_to]

# blob-less clone
$ git clone --fliter=blob:none [url] [clone_to]

2-2-2. completeリポジトリからpartial-cloneリポジトリへの変換

既存のリポジトリをblob-lessに変換する例.

# blob-less clone リポジトリへのconvert
# 下記の設定を追加
$ git config remote.[remote_name].promisor  true
$ git config remote.[remote_name].partialclonefilter  blob:none
# 不要なlocalオブジェクトを破棄. (git のバージョンに注意. filter-toは最近追加されたもの)
# filter-toには除外ファイルのprefixを指定する. 
# ./hoge/fugaのようにファイルパスでprefixを指定すれば、別ディレクトリへの出力も可能.
$ git repack -ad --filter=blob:none --filter-to=pack --no-write-bitmap-index
# 除外したオブジェクトのファイルを削除
$ rm -f pack-*

2-2-3. partial-cloneリポジトリからcompleteリポジトリへの変換

# partial-cloneのフィルタ設定を削除
$ git config --unset remote.[remote_name].partialclonefilter
# リポジトリデータの再fetch
$ git fetch --refetch
# (任意) refetchの結果、リポジトリサイズが通常のcomplete-cloneリポジトリよりも大きくなることがある.  
# 重複した情報のオブジェクトをpackから削除して整理する
$ git gc --aggressive

3. 必要なファイルのみをcheckoutする(sparse-checkout)

submoduleで他プロジェクトを参照するときなどは、プロジェクトの一部ファイルのみさえあればよいといった状況があります.
sparse-checkoutでは、作業領域に展開するファイルを指定したファイル/ディレクトリのみに限定します.
ブランチを切り替えるときに、すべてのファイルをローカルに再現する必要がなくなるので、checkoutによるブランチ切り替えが高速になります.

3-1. sparse-checkoutを設定する

コマンドで設定する場合は以下の手順を行います.

# sparse-checkoutの適用(.git/info/sparse-checkout の新規作成)
$ git sparse-checkout init
# chekcout対象を限定する
# hogeディレクトリとfugaディレクトリに限定
$ git sparse-checkout set hoge/ fuga/
# 対象の追加など
$ git sparse-checkout add hoga/

3-2. sparse-checkoutファイルを直接編集して適用

.git/info/sparse-checkoutファイルを直接作成/編集しても設定ができます.
.gitignoreと同じ書式で対象ディレクトリ/ファイルを指定します.
ファイル単位の指定は、.git/info/sparse-checkout ファイルを直接編集することで指定ができます.
直接編集したあと、後述の git sparse-checkout reapply で作業領域に適用します.

# ## sparse-checkoutファイルの例 ## 
# root直下のファイルをcheckout
/*
# 先頭に!をつけるとNot条件になります
# root直下にあるディレクトリはcheckoutしない
!/*/
# root直下にあるhogeディレクトリ以下はcheckoutする
/hoge/
# root直下にあるfugaディレクトリ以下はcheckoutする
/fuga/

3-3. sparse-checkoutを反映

info/sparse-checkoutファイルをもとに、ファイルの内容を作業領域へ反映します.

# sparse-checkoutの設定
$ git sparse-checkout reapply

3-4. sparse-checkoutの設定解除

以下コマンドを実行するとsparse-checkoutが解除できます.

# sparse-checkoutの適用解除
$ git sparse-checkout disable

解除後は, 再度 reapplyすることで再設定ができます.

参考情報

Debug構成以外でもライブビジュアルツリーからXamlへのコードジャンプを有効にする

Live Visual Tree のコードジャンプ

VisualStudioのデバッグツールには実行中のWPFアプリのUIコンポーネントをツリー形式で表示する ライブビジュアルツリーという機能があります.
この機能、すべての構成で表示はできるのですが、コンポーネント横に表示されるアイコンをクリックして対応しているXamlファイルへジャンプする機能は Debug構成のみでしか有効になっていません。

しかし、Debug構成以外であってもUI構成を解析するなど使用したいことがあります.

Debug構成以外でXamlへのコードジャンプを有効にする

ライブビジュアルツリーウィンドウから Xaml ファイルへのコードジャンプを有効にする設定は、 Visual Studio上からは行えないようで、csprj ファイルを直接編集します.

(1) デスクトップアプリのプロジェクト

デスクトップアプリのプロジェクトの場合は、有効にしたいビルド構成の PropertyGroup 以下に XamlDebuggingInformation 要素を挿入して、値をTrueにします.

  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'RelWithDebInfo|x64'">
    <DebugSymbols>true</DebugSymbols>
    <OutputPath>$(SolutionDir)x64\$(Configuration)\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <Optimize>false</Optimize>
    <DebugType>full</DebugType>
    <PlatformTarget>x64</PlatformTarget>
    <UseVSHostingProcess>true</UseVSHostingProcess>
    <!-- この要素を挿入 -->
    <XamlDebuggingInformation>true</XamlDebuggingInformation>
    <!-- この要素を挿入 -->
    <ErrorReport>prompt</ErrorReport>
    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
    <Prefer32Bit>true</Prefer32Bit>
  </PropertyGroup>

(2) UWPアプリのプロジェクトの場合

UWPアプリの場合は、DisableXbfLineInfo 要素を挿入して、値をFalseにします.

参考リンク

Troubleshooting XAML Hot Reload - Visual Studio (Windows) | Microsoft Learn

[メモ] リファレンスブックマーク

リファレンスブックマーク集

PortableなLinuxバイナリの作り方

$ORIGINについての解説あり nehckl0.medium.com

RunLevelの変更

永続的なrunlevelの変更

www.server-world.info

一時的にrunlevelを落として起動するための処置.

www.if-not-true-then-false.com

xtech.nikkei.com

systemctrl を使った変更 atmarkit.itmedia.co.jp

仮想マシン向け I/O schedulerの変更

I/Oスケジューラの設定を一時的に変更

LinuxでのディスクI/Oスケジューラの検証

udevのrulesファイルを使用してschedulerの変更を自動化. manual.sakura.ad.jp

GRUB2で一時的にRunLevelを変更して起動する

一時的にRunlevelを変更して起動したい.

Guiに何らかの問題があり正しくdesktopモード(runlevel5)Bootしなくなったときなどに 一時的にrunlevelを落として起動するための処置.

www.if-not-true-then-false.com

linuxのある行の最後にrunlevelを数値指定すれば良いようです.
この変更は一時的で、次回Boot時にはもとに戻るようです.

Ubuntu 22.04.1 ある日突然 Dummy Output になった問題

ある日突然音声出力が Dummy Output に

apt full-upgradeしたら 突然Soundが Dummy Output となって音声がでなくなる現象に遭遇しました.
PluseAudio絡みの問題かと思い、色々調べてみますが一向に解決せず。

askubuntu.com

apt upgradeで誤ったカーネルがインストールされてしまっていた

よくよく調べてみると、音声がでなくなるだけでなくいろいろ起動しなくなっている様子。

  • ディスプレイが自動でOFFにならない
  • VirtualBoxがエラーで起動しない

これはPluseAudio絡みではなくカーネルの問題ではないか・・・?、とカーネルのバージョンを調べたら・・

ん??

$ uname -r 
5.15.0-1025-oracle

なんて知らないバージョンが勝手にinstallされて使われてました.
どうやら最近のupdateで起こったバグのようです.

askubuntu.com

ネットワークなんかも動かなくなっているケースがあるようですね..

issueも上がっていました.

bugs.launchpad.net

ということでGrub2で正しいカーネルを指定して再起動し、知らないバージョンのカーネルイメージを削除して無事解決しました.

$ sudo apt remove linux-image-5.15.0-1021-intel-iotg linux-image-5.15.0-1025-oracle linux-modules-5.15.0-1021-intel-iotg linux-modules-5.15.0-1025-oracle linux-modules-5.15.0-56-lowlatency linux-image-5.15.0-56-lowlatency

参考サイト

VirtualBox の Guest OS 上でビルドすると internal compiler error が多発する現象 (Ubuntu 22.04.1)

Guest OS 上でビルド中 internal compiler error が発生してビルドできない・・・

ある日突然仮想マシン上の Guest OSでビルドすると internal compiler error が多発する現象に遭遇.

apportのログを見ると、ビルド中に Segmentation Fault が発生してビルドが中断している模様.
しかし、コードに問題があるわけではなく発生箇所は毎回変化し、ビルドを再開すると、しばらくビルドが進んでまた internal compiler error が発生.

これ、 通常であればコンパイラバグ、ハードウェアの問題かカーネルバグを疑うべきところなんですが・・・

  • 今回は、エラーが毎回違う場所で発生しているので、コンパイラのバグの可能性は薄い.
  • Guest OS でのみ発生しており、Host OS 側は何の問題もありませんから、マシンのハードウェアの可能性は薄い.
  • Guest OS のメモリ不足も疑うべきですが、Guest OS へのメモリ割当ては16Gと十分でこれも可能性は薄い.

となると・・残るはVirtualBoxが怪しいということに・・

Ubuntu公式リポジトリVirtualBoxとホスト側カーネルの不整合が原因

VirtualBoxUbuntu 22.04.1 で似たような問題が起きてないか漁っていると・・・
以下に同じ現象がpostされているのを発見.

askubuntu.com

この現象、 ホスト側カーネルlinux-image-5.15.0-47-generic だと発生し、一つ前のカーネル linux-image-5.15.0-46-generic では発生しないそうで.
カーネルバージョンとvirtualboxのバージョンの組み合わせで発生する問題なのだとか・・・.

公式リポジトリのパッケージの組み合わせで発生しちゃうので、apt-get dist-update (apt full-upgrade) したらある日突然に、新規で環境を作る場合はいきなりこの現象に遭遇することになるわけです.
これは結構・・心臓に悪いですね・・・.

公式リポジトリVirtualBoxOracle提供のものに変更すれば解決.

解決にはOracleが提供するVirtualBoxの最新版に変更すればよいようです.

Ubuntu公式リポジトリ由来の virtualbox と関連パッケージをすべて削除して、Oracle版のもののみをインストールします.
aptの依存関係による自動削除に任せるとUbuntu公式由来の依存パッケージが残ってしまうことがあるので、packageの依存関係を確認して、削除するパッケージを各々個別に指定して確実に削除する必要があります .
Ubuntu公式リポジトリ由来のパッケージが残っていると、ゲストOS起動時にエラーになったりCrashしたりしますので注意.

# Oracleのリポジトリと公開鍵を追加
$ sudo echo "deb [arch=amd64 signed-by=/usr/share/keyrings/oracle-virtualbox-2016.gpg] https://download.virtualbox.org/virtualbox/debian jammy contrib" > /etc/apt/sources.list.d/virtualbox.list
$ wget -O- https://www.virtualbox.org/download/oracle_vbox_2016.asc | sudo gpg --dearmor --yes --output /usr/share/keyrings/oracle-virtualbox-2016.gpg
# パッケージ情報更新
$ sudo apt update

# 公式リポジトリ由来のvirtualboxと関連パッケージを明示的に削除.
$ sudo apt purge virtualbox virtualbox-dkms virtualbox-ext-pack virtualbox-qt
# Oracleのvirtualboxをインストール
$ sudo apt install virtualbox-6.1

Oracle版の VirtualBox を立ち上げて Guest OS が問題なく起動できれば無事完了です.
これで、ビルド時に internal compiler error が頻発する現象も解消されました.

参考サイト

These articles have been very helpful for me. thanks!!