しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

Surface Laptop 3 から Surface Laptop 4 に乗り換えた

タイトルの通りですが、1 年半ぐらい使っていた Surface Laptop 3 から Surface Laptop 4 に乗り換えました。購入したのは 13.5" / マットブラック / Core i7 / 32GB RAM*1 / 1TB SSD のモデルです。

元々マットブラックを買うつもりだったので問題はなかったのですが、32GB が選べるのは 1TB + マットブラックのみだったのは少し残念でした。受注生産扱いならカスタマイズさせて欲しいです。

f:id:shiba-yan:20210416194539j:plain

Surface Laptop 3 もかなり良いマシンでしたが、Visual Studio を使って開発していると結構熱くなって、CPU クロックが全然上がらないことが多かったのと、やっぱりメモリ 16GB は結構しんどい場面があったので、32GB モデルの存在を見て思い切りました。

正直なところ CPU とメモリ以外に変更点はなさそうですが、その二点に不満があったので問題ないです。

Core i7-1185G7 が載っていますが、28W で動作しているらしくベースクロックは 3.0GHz になっていました。Tiger Lake から TDP という概念が変わったらしいです。

f:id:shiba-yan:20210417000032p:plain

カタログスペックの時点で Laptop 3 に載っていた Core i7-1065G7 より断然クロックが高いので、シングルスレッド性能が期待できます。

何だかんだでマルチスレッド性能よりシングルスレッド性能が高い方が快適度も高いです。

例によって CPU-Z で詳細と簡易ベンチマークだけ取っておきます。TB で 4.8GHz まで上がる CPU です。

f:id:shiba-yan:20210416233810p:plain

CPU-Z ではメモリチャネルがクアッドとして表示されていましたが、そもそも CPU がデュアルまでしか対応していないので間違って認識しているっぽいです。

f:id:shiba-yan:20210416233821p:plain

ちなみにメモリは順当に LPDDR4x-4266 へとアップグレードされています。発表時には LPDDR4X-3733 と書かれていたメディアが多かったですが、正しくありませんでした。

搭載されている SSD はサムスン製だったので、Surface Laptop 4 は以下の記事で紹介されている Intel のリファレンスに近い構成になっているようです。

Surface Laptop 4 は開発用なのでグラフィックス性能はあまり興味ないのですが、適当に設定を見ていたら可変リフレッシュレートが使えるようになっていました。

f:id:shiba-yan:20210417001942p:plain

VRR は Gen 12 のグラフィックスから追加されたらしいです。USB-C を使ったモニタ接続はまだ試せていないですが、Laptop 3 で問題なかったので大丈夫だと思っています。

ここから先は毎回調べている CPU と SSD の簡易ベンチマークです。

CPU - Laptop 4

前評判通り Tiger Lake のシングルスレッド性能はかなり良くなっていました。ちなみに Windows の電源設定によって性能が変わるので、最大パフォーマンスに設定しています。

f:id:shiba-yan:20210416233924p:plain

シングルスレッド性能だけ見ると、以下のエントリで調べた Ryzen 9 5950X に近い値が出ているので、モバイル向け CPU にしておくのはもったいない感じがあります。

Laptop 4 では Windows の電源設定スライダーを弄っても、常時高クロックで動くのではなく必要な際にブーストクロックが向上するような挙動になっていました。Laptop 3 では最大パフォーマンスにすると常時最高クロックで動いていたので、効率が悪いなと思っていました。

つまり Laptop 4 では電源設定のスライダーを弄ると、本当にパフォーマンスが上がるということです。

CPU - Laptop 3

Laptop 3 でも電源設定は最大パフォーマンスにしていますが、特に変化はありませんでした。

f:id:shiba-yan:20210416233906p:plain

Laptop 4 の性能を見てしまうと、Ice Lake はかなり遅かったのだなと認識してしまいます。

SSD - Laptop 4

正直なところ PCIe 4.0 の SSD を載せておいて欲しかったのですが、そもそも M.2 2230 で対応したものが存在していないようなので難しかったのかもしれません。

載っていたのはサムスンの PM981 っぽいですが、ぶっちゃけ結構遅いです。

f:id:shiba-yan:20210416233935p:plain

シーケンシャルリードが何でこんなに遅いのかは謎なので、時間を空けて確認してみようかと思います。

SSD - Laptop 3

Laptop 3 の東芝製 SSD は Laptop 4 と比べるとかなり早かったことを再認識しました。

f:id:shiba-yan:20210416233942p:plain

購入して、かなり使用した後でも Laptop 4 の SSD より性能が良かったです。

SSD に関してはモデルや購入タイミングによって差がありそうですが、今回は残念な気持ちが大きかったです。とは言っても十分な性能ではあるのと、CPU 周りがメインなので開発用として活躍してもらいます。

流石に Surface Laptop 5 は買わない可能性が高そうですが、日本語キーボードのレイアウトが Laptop Go や Designer Compact Keyboard と同じになれば検討しようと思います。

*1:4 かずあき

.NET 6.0 Preview で WPF が ARM64 に対応したのでビルドして Surface Pro X で試した

.NET 5.0 で Win Forms は ARM64 の Windows に対応しましたが、WPF は 2021 年に先送りになっていて非常に残念でしたが、最近リリースされた .NET 6.0 Preview の Nightly Build でついに対応しました。

GitHub の Issue ではマイルストーンが 5.0.0 になっているので、バックポートされるのかも知れません。

既に Twitter では .NET 6.0 Preview で WPF アプリケーションを ARM64 向けにビルドして動かした例が上がっていたので、自分も WPF アプリケーションを公開しているのでビルドを試しておきました。

アプリケーションは Windows Store に公開しているので MSIX まで作成できることを確認しておきました。

まずはシンプルな WPF アプリケーションを使って確認することにします。適当に .NET 6.0 Preview SDK の Nightly Build をインストールして、最近の Visual Studio Preview で WPF アプリケーションを作成すると .NET 6.0 が選べるので、ここから始めます。

f:id:shiba-yan:20210131182422p:plain

とりあえず ARM64 向けにビルド出来るかの確認をしておきたいので、以下のようなコマンドで RID として win-arm64 を指定してビルドします。ReadyToRun も確認してみましたが問題ありませんでした。

この時パッケージの復元でエラーになることがありますが、その場合は .NET 6.0 の Nightly 向け NuGet パッケージソースを追加すれば解決します。

# ARM64 Windows 向けに発行
dotnet publish -c Release -r win-arm64 -o ./publish

# ARM64 Windows 向けに ReadyToRun を有効にして発行
dotnet publish -c Release -r win-arm64 -o ./publish -p:PublishReadyToRun=true

ちなみに .NET 5.0 では WPF に非対応なのでビルド時にエラーになります。

ビルドした dll を dumpbin で確認すると、ちゃんとヘッダーのアーキテクチャが AA64 になっているので ARM64 向けにビルドされていることが分かります。

f:id:shiba-yan:20210131182431p:plain

RID を指定してビルドすると Self-Contained アプリになるので、出力されたファイル一式を Surface Pro X などの ARM64 Windows 上にコピーして持っていくと、それだけで動くようになります。

Self-Contained でファイル数が多いからか、若干時間がかかった気がしましたが無事に起動しました。Surface Pro X 上で 64 bit プロセスとして認識されているので ARM64 です。

f:id:shiba-yan:20210131183459p:plain

.NET CLI を使ったビルドは問題ないことが分かったので、MSIX を各プラットフォーム分作成できれば Windows Store で公開しているアプリケーションの移行がスムーズに出来るはずです。

正直なところ MSIX の作成は結構はまりましたが、最終的には WPF 側の csproj を以下のように定義することで、いい感じに各プラットフォーム向けに ReadyToRun 付きで MSIX をビルドできるようになりました。

何故かこの辺りは情報が非常に少なくて正解なのか分からないですが、各プラットフォーム向けのビルドと MSIX の作成は問題なく動いています。.NET Core 系では RID を指定すれば何とかなる感じはあります。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net6.0-windows</TargetFramework>
    <UseWPF>true</UseWPF>
    <Platforms>x86;x64;arm64</Platforms>
    <RuntimeIdentifier>win-$(Platform)</RuntimeIdentifier>
    <PublishReadyToRun>true</PublishReadyToRun>
  </PropertyGroup>

</Project>

WPF アプリケーションを作成すると Any CPU 向けで基本は作成されますが、Windows アプリケーションパッケージプロジェクトを追加すると x86 や x64 向けのプラットフォームが自動で作成されます。

この設定と WPF アプリケーションがビルドされる時の RID をキッチリ合わせておかないと、大体の場合は x86 以外のビルド時にエラーとなります。具体的には csproj に Platforms を追加して、構成マネージャーからソリューションプラットフォームへのマッピングを行います。

f:id:shiba-yan:20210131191016p:plain

この時に必要ない Any CPU や ARM 向けのソリューションプラットフォームは削除しておきました。後はソリューションプラットフォームの ARM64 が大文字になっていますが、RID は case-sensitive なので全て小文字に変更しておきます。*1

ビルドした msixbundle ファイルを Surface Pro X にコピーしてインストールして試しましたが、問題なく ARM64 で実行されました。特に ARM64 で動くことによって見た目に違いがあるわけではなく、面白みがないのでインストーラー画面だけ拾ってきました。

f:id:shiba-yan:20210131191656p:plain

msixbundle ファイルには x86 / x64 / ARM64 それぞれの実行ファイルが含まれているので、自動的に適切なプラットフォーム向けのものがインストールされます。

サンプルプロジェクトで ARM64 向けビルドと MSIX の作成まで問題なく行えたので、メインターゲットである WinQuickLook でも ARM64 向けビルドを試しましたが、ALINK でエラーが出て成功しませんでした。一応 ARM64 に対応するための PR だけは作成してあります。

エラーの原因を調べたところ、ALINK が ARM64 に対応していないのが根本原因でした。ALINK がそもそも使われる理由は WPF アプリケーションでサテライトアセンブリのためなので、多言語対応のリソースファイルを削除して 1 つにすると通るようになりました。

ローカライズに WPF 側の仕組みを使うのではなく、MRT と PRI に移行することで解消はしそうですが、このあたりの情報もさらに少ないので非常に悩むところです。

WinUI 3.0 や Project Reunion が正式リリースされたタイミングで改善される気はしますが、この辺りはまだまだ時間がかかりそうなのでしばらくはこれまでのリソース管理を使い続ける予定です。

*1:例えば RID として win-ARM64 を指定するとビルドエラーになる

Surface 用に Microsoft USB-C トラベルハブを買ってみたけど残念な結果になった

常時 Surface Laptop 3 と共に USB-C to HDMI / USB-A to Ethernet / USB-C to USB-A といった各種アダプターを持ち歩いてきましたが、Microsoft から公式の USB-C トラベルハブが出ると聞いたので飛びつきました。

意外に良い値段がしますが、USB-C 関連製品は高いものが多いので諦め気味です。

買ったのは良いのですが、残念な点が大きかったので共有の意味も込めて書いておきます。

買って良かった点

思ったより大きくなくて、これまで持ち歩いていた 3 種類以上のアダプターを統合するものとしては、高級感もあってかなり良い感じでした。USB-C のケーブルを本体に磁石で固定できるのは良かったです。

f:id:shiba-yan:20200610181828j:plain

今更 VGA が必要なのかという気はしますが、HDMI と VGA の両方に対応しています。ちなみに同時に画面出力が行えるというわけではなく、HDMI 側が優先される仕様のようです。

Surface Laptop 3 には USB-C と USB-A が 1 つずつなので、USB-A が増えるのは結構便利そうです。

f:id:shiba-yan:20200610182248j:plain

ちなみに最初にアダプターを接続すると Ethernet 周りのドライバーがインストールされました。

f:id:shiba-yan:20200610181328p:plain

Surface 以外にも USB-C に対応したデバイスなら使えるようです。自分は Surface でしか使いませんが。

とても残念な点

予約した時は Surface Laptop 3 への USB-C 経由での充電まで行えるのかと思っていましたが、届いた箱の裏には以下のような記述がありました。なんとパススルー充電に非対応です。

ちなみにトラベルハブ側の USB-C は Alt Mode 非対応らしく、画面出力は行えませんでした。パススルーでの充電も行えないので、ここの USB-C は正直なところ利用価値がほぼないです。

Microsoft または Surface USB-C Travel Hub の使用

これまで持ち運んでいた USB-C to HDMI、USB-A to Ethernet、USB-C to USB-A の変換アダプターを全て 1 つのトラベルハブに置き換えることが出来ましたが、USB-C 経由での充電が行えないのでかなり残念です。

この金額を出して買うなら、USB-C でのパススルー充電に対応したものを買っておいた方が良いと思いました。前に iPad Pro で試したこれとかは充電も出来てよかったです。

最近は充電を iPhone 以外は USB-C にまとめていますが、このトラベルハブを使う場合はバッテリー稼働にするか、Surface Connect のケーブルを持ち歩くしかないようです。かなり嫌な選択肢です。

Electron で Surface Pro X にネイティブ対応したアプリを作る

Surface Pro X というか ARM64 にネイティブ対応したアプリケーションが中々増えないですが、.NET Framework / .NET Core 以外ならいい感じに ARM64 対応が進んでいます。

特に Electron 7 から ARM64 対応したのは結構インパクトが大きいと思っています。

Electron の公式ドキュメントに Windows on ARM 向けのチュートリアルが用意されていますが、微妙に古い情報だったので最新の Electron 8 と Visual Studio 2019 で試してみました。

と言っても自分は Win32 とか Windows on ARM に関する知識はあっても Electron 周りの知識はほぼないので、サンプルプロジェクトを全編通して利用しています。

ARM64 ネイティブで動くと、常駐するタイプのメッセージングアプリで有利になってくるはずなので、是非とも Slack や Teams には対応してほしいところです。てか Teams は出すべき。

とりあえず Electron サンプルを動かす

前述したように Electron の経験がゼロなので、まずは普通の Windows 10 上で Electron のサンプルをビルドして動かしてみました。今回は公式の Quick Start を利用しました。

Node.js がインストールされていれば、以下のコマンドを叩くだけでアプリケーションが起動します。

git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install
npm start

実際に起動した例は以下になります。見慣れたインターフェースを持つアプリケーションが起動しました。

f:id:shiba-yan:20200416015437p:plain

Node.js の Web アプリケーションを動かすのとほとんど変わらない手順で Electron のアプリケーションが起動できました。このアプリケーションを Surface Pro X 上でネイティブ動作するように持っていきます。

実行可能ファイルとしてビルド

Electron を使ったアプリケーションを実行可能ファイルにするには electron-packager というツールが公式に提供されているようですが、最低限の機能しか持っていないようなので、インストーラ付きでビルドできる electron-builder を使った方が便利なようです。

使い方も簡単で、公式ドキュメントの通りに npm を使って electron-builder をインストールします。

npm install -D electron-builder

インストール後に packages.jsonscripts にコマンドを追加しつつ、同時に build セクションを追加しておきます。スクリプトベースでも定義できるようですが、簡単な方を選びました。

{
  "name": "electron-quick-start",
  "version": "1.0.0",
  "description": "A minimal Electron application",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "pack": "electron-builder --dir",
    "dist": "electron-builder"
  },
  "build": {
    "appId": "SampleApp"
  },
  "author": "GitHub",
  "license": "CC0-1.0",
  "devDependencies": {
    "electron": "^8.2.4",
    "electron-builder": "^22.6.0"
  }
}

appId は無くてもビルドは通りますが、ドキュメントには明示的に指定するように強く書かれていたので設定しています。本来ならユニークな値を設定する必要があります。

設定完了後に npm run dist を実行すると実行ファイルが生成されます。

f:id:shiba-yan:20200429193134p:plain

アイコンなどのリソースは決められたパスにファイルを置いておけば自動的に使われます。指定しない場合は Electron のデフォルトアイコンのままになるので、実際のアプリ開発時には用意しておきましょう。

複数アーキテクチャ対応のインストーラーを作成

デフォルトの設定のままでは x64 向けの実行可能ファイルが生成されましたが、アプリケーションの配布時には複数アーキテクチャに対応したインストーラーが必要になってきます。

Electron では Windows 環境において ia32 (x86) / x64 / arm64 がサポートされています。

electron-builder を使って複数アーキテクチャに対応させるには win セクションを追加して、その中でビルドするアーキテクチャを指定します。

以下のように書くと Windows で利用可能な全てのアーキテクチャ向けにビルドします。

{
  "name": "electron-quick-start",
  "version": "1.0.0",
  "description": "A minimal Electron application",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "pack": "electron-builder --dir",
    "dist": "electron-builder"
  },
  "build": {
    "appId": "SampleApp",
    "win": {
      "target": {
      	"target": "nsis",
      	"arch": ["ia32", "x64", "arm64"]
      }
    }
  },
  "author": "GitHub",
  "license": "CC0-1.0",
  "devDependencies": {
    "electron": "^8.2.4",
    "electron-builder": "^22.6.0"
  }
}

x86 ではなく ia32、amd64 ではなく x64 と書く必要があるのが少し罠っぽいです。若干統一感に欠ける印象がありますが、間違った場合にはビルドエラーになるのですぐに気が付くはずです。

これも先ほどと同様に npm run dist を実行するとインストーラー付きで作成されます。

f:id:shiba-yan:20200429204541p:plain

このインストーラーを Surface Pro X にコピーして実行してみると、問題なく arm64 版がインストールされてアプリケーションが動作していることが確認できます。

Surface Pro X 上では 64bit プロセスは ARM64 で動作している場合だけなので、タスクマネージャーから簡単に確認することが出来ます。

f:id:shiba-yan:20200429203052p:plain

Quick Start は特にプラットフォームに大きく依存するものを使っておらず、外部のライブラリも参照していないので簡単に ARM64 向けビルドが行えました。

しかし普通は何かしらライブラリを使うはずなのでその辺りも検証していきます。

Native Module をビルドして利用

Node.js のモジュールにはネイティブコードを使うものがあり、通常なら node-gyp でいい感じにビルドするか、node-pre-gyp でビルド済みバイナリをダウンロードするのであまり気にする必要がないです。

現状 Windows 10 の ARM64 向けバイナリはほぼ提供されていないので、自前でビルドする必要があります。Electron 向けにビルドするのはドキュメントがありますが割とめんどくさい感じです。

しかし electron-builder は自動的に上のドキュメントにある処理を行ってくれるので、何も考えなくてもコマンドを叩くだけで ARM64 向けビルドが行えます。

実際にビルドが必要になるライブラリで試してみます。今回は bcrypt を使ってみました。

npm install bcrypt

ARM64 向けのビルドを行うためにはコンパイラーやライブラリをインストールする必要があるので、予め Visual Studio Installer からインストールしておきます。

f:id:shiba-yan:20200430165434p:plain

これまでのように npm run dist を実行するだけで、bcrypt のビルドが実行されていることがログから確認できます。ARM64 の場合は node-gyp によってビルドが行われています。

f:id:shiba-yan:20200430163456p:plain

Native Module を使っていても、electron-builder を使っていれば自動でビルドが走るので便利です。ただしビルド対象のライブラリが ARM64 向けにコンパイルできないコードの場合はエラーになります。

アプリケーションを AppX としてビルド

インストーラーとしてこれまでビルドしてきましたが、Windows Store での配布を行う場合には AppX や MSIX としてビルドする必要があります。electron-builder は AppX としてのビルドに対応しているので、多少の設定変更でビルド出来ます。

設定は以下のように変更しています。変更点としては targetappx に変更し、appx セクションを追加しているぐらいです。AppX の場合は identityName の設定は必須のようです。

{
  "name": "electron-quick-start",
  "version": "1.0.0",
  "description": "A minimal Electron application",
  "main": "main.js",
  "scripts": {
    "start": "electron .",
    "pack": "electron-builder --dir",
    "dist": "electron-builder"
  },
  "build": {
    "appId": "SampleApp",
    "win": {
      "target": {
        "target": "appx",
        "arch": ["ia32", "x64", "arm64"]
      }
    },
    "appx": {
      "identityName": "ElectronQuickStart"
    }
  },
  "author": "GitHub",
  "license": "CC0-1.0",
  "devDependencies": {
    "electron": "^8.2.4",
    "electron-builder": "^22.6.0"
  },
  "dependencies": {
    "bcrypt": "^4.0.1"
  }
}

electron-builder のバージョンは 22.6.0 以上を使わないと、ARM64 向けビルドの時にエラーになります。

これまでのようにビルドを行うと、各アーキテクチャ向けに AppX が生成されます。

f:id:shiba-yan:20200430170351p:plain

appxbundle は生成されないですが、Windows Store へのアップロード時には appx で問題ないです。

appx を開いてみるとインストーラーが立ち上がります。署名がないので今はインストールエラーになりますが、Windows Store へのアップロード目的の場合は署名無しで問題ありません。

f:id:shiba-yan:20200430225908p:plain

サイドローディングの場合は署名を行う必要がありますが、これもまた electron-builder が対応しています。

アプリケーションに署名を行う

electron-builder を使うと PFX とパスワードだけ用意しておけば簡単に署名が行えます。証明書はとりあえず自己署名証明書を作成して試すので、PowerShell を使って適当に PFX を作成しておきました。

署名の設定は環境変数を使って行うので、CI でも簡単に実行可能でしょう。以下のような環境変数を設定しておけば、自動的に署名が実行されます。

set CSC_LINK=certificate.pfx
set CSC_KEY_PASSWORD=P@ssw0rd

ビルド後に署名されているか確認するには、AppX のファイルプロパティを開くだけです。

f:id:shiba-yan:20200430231237p:plain

Windows Store 以外からインストールするためには信頼済みの署名が必要なので、認証局から発行されたコードサイニング証明書を使うか、自己署名証明書を「信頼されたルート証明機関」に入れる必要があります。

証明書をインストールすれば、appx を開いたときに警告が表示されなくなります。

f:id:shiba-yan:20200430232435p:plain:w550

これでインストールが完了したので、後はスタートメニューからアプリケーションを選べば起動出来ます。

f:id:shiba-yan:20200430232445p:plain

思ったより Electron のビルド周りのインフラが洗練されているという印象を持ちました。

外部のライブラリ次第ではありますが ARM64 への対応も比較的簡単になっているので、対応アプリが増えていくことを期待しています。まずは Teams は何とかしてほしい。

技適未取得機器の特例制度を使って Surface Pro X の検証を出来るようにした

11/20 から開始された技適未取得機器を用いた実験等の特例制度を使って、Surface Pro X の Wi-Fi / Bluetooth を使った検証を行えるようにしました。Surface Pro X は ARM64 の CPU を載せているので、アプリケーション開発者としては検証環境として非常に重要です。

最初は勘違いしていましたが、この特例制度を使って試せるのは Wi-Fi と Bluetooth で LTE は無理です。

なのでスマホなどの LTE 周りは非常に難易度が高いですが、アプリケーションの検証には Wi-Fi が使えれば大体良いので、今回の Surface Pro X にとっては最適な感じです。

届出に必要な情報を集める

送信出力が 200mW 以下のデバイスのみ対象になっていたので、FCC ID を確認して調べておきました。Surface の FCC ID は以下のページにまとめられているので、簡単に調べることができます。

https://support.microsoft.com/en-us/help/4465092/regulatory-information

便利なサイトがあったので、こちらを使って出力が範囲内か確認しておきました。

Surface のモデル名は Surface アプリを使うか、キックスタンドの裏とかを探せば書いてあります。

f:id:shiba-yan:20191120144943p:plain:w550

他にもシリアル番号も必要だったので、同じく Surface アプリから確認できたものを使いました。

実際の申請の流れ

総務省の電波利用ホームページから空メールを送信すると、届出書作成支援ツールへのリンクが返ってくるので、そのページから必要な情報を入力して届出書を作成するだけでした。

既報の通り個人の項目もあったので簡単でした。一通り入力後は印刷してサインするだけで終わったので、思ったより手間はかからなかったです。作成した届出書は郵送すれば良いのですが、今回は九段にある総務省 関東総合通信局に直接持ち込んできました。

お昼直前に持ち込んできましたが、明らかに自分以外に誰も持ち込んでなさそうな雰囲気でした。簡単にデバイスと実験内容について聞かれたぐらいで受理されました。

持ち込みの場合は即日と聞いていましたが、お昼後には受付のメールが届きました。このメールが届いた後から実際に利用が可能となるようでした。

このメールには変更や廃止に必要な一時コードが載っているので、削除しないように大切に保存します。

これで Surface Pro X の Wi-Fi と Bluetooth が 180 日間、実験目的で使えるようになりました。

f:id:shiba-yan:20191120161617p:plain:w650

f:id:shiba-yan:20191120151132j:plain

しっかりと x86 エミュレーションの検証や ARM64 への動作確認を行っていきます。

Surface Pro X がサポートする CPU アーキテクチャとアプリケーション側の対応

最近は Surface Pro X (Windows on ARM) について色々と調べたり、アプリケーションをデプロイして試したりしてますが、やはりパフォーマンスを考えると ARM64 への対応が必要だと再認識しているのと、どうにも誤解が多そうなのでまとめました。

基本的な Surface Pro X の情報は既に購入時のレポートに書いたので参照してください。

既に知られている通り x64 には対応していないですが、x86 と ARM32 は WOW64 によって対応しています。

WOW64 のドキュメントにはひっそりと ARM64 に関する情報が追加されています。

  • (ARM64 only) xtajit.dll contains the x86 software emulator.
  • (ARM64 only) wowarmw.dll provides support for running ARM32 programs on ARM64.
WOW64 Implementation Details - Win32 apps | Microsoft Docs

WOW64 による ARM32 と ARM64 の関係は x86 と x64 の関係と同じです。

結果として Surface Pro X は ARM64 / ARM32 / x86 の 3 つの CPU アーキテクチャに対応したアプリケーションを実行できますが、以下に軽くまとめたように動かし方が異なっています。

  • ARM64
    • ネイティブ実行
  • ARM32
    • WOW64 で実行
  • x86
    • WOW64 + エミュレーションで実行

ARM32 の WOW64 でのパフォーマンスがどのくらい ARM64 と差が出るのかは確認が難しいですが、確実に x86 の WOW64 + エミュレーションよりは速いです。

ここまでの内容を頭に入れておくと、System32 周りのディレクトリの意味が分かってきます。

ここから先は Surface Pro X でそれぞれの CPU アーキテクチャに対応したアプリケーションを、実際に動かしてみた例になります。窓の杜がいつの日にか ARM64 対応の一覧を作ってくれることを願います。

ARM64 (ネイティブ)

当然ながら WOW64 やエミュレーションによるオーバーヘッドが存在しないので、理論上は ARM64 に対応したアプリケーションが Surface Pro X 上は一番快適かつ効率的に動作するはずです。

Chromium Edge (Canary)

確実に Surface Pro X 向けと思うタイミングで Chromium Edge の ARM64 対応バージョンが出ました。

バージョンを確認しても 64bit と書いてあるだけで、特に ARM64 という感じはしないです。

同時に Beta もインストールしていたので比較しましたが、明らかにアプリケーションの起動速度とページ表示速度が向上していたので、ブラウザは ARM64 対応が必須という感じがしました。

Firefox (Beta)

Firefox も Beta ですが ARM64 に対応したバージョンがリリースされています。Chromium Edge より全体的にキビキビ動いてる感じがしましたが、ベンチマーク的には Chromium Edge のが上のようでした。

Chromium Edge と同じくバージョン情報では 64bit とあるだけですが、ちゃんと ARM64 で動いてます。

対応開始から 1 年近く経っているからか、完成度は Chromium Edge より高いと感じました。正式版がいつ出るのかは軽く調べましたが分かりませんでした。

Windows Terminal (Preview)

新しいアプリだけあって最初から ARM64 に対応しているのは偉いと思いました。

f:id:shiba-yan:20191116172522p:plain

問題なく動くので特筆するべきことはないです。ぶっちゃけ x86 でもあまり変わらない気も…。

VLC for Windows

ARM64 に対応したアプリケーションを探していたら、VLC for Windows が見つかりました。ちなみに Store 版は ARM32 への対応なので、Windows 10 Mobile 向けのおこぼれという感じです。

f:id:shiba-yan:20191116181848p:plain

ビルドが去年から更新されていなさそうなので今後が少し心配ではありますが、非常に低い負荷でメディアの再生が可能なので結構良い感じでした。

WSL (Ubuntu / Debian / Fedora Remix など)

WSL 向けのディストリビューションはそこそこ ARM64 対応がされているので選択肢が多いです。

f:id:shiba-yan:20191116203018p:plain

来年リリース予定の WSL2 でも仮想化に対応していれば ARM64 でも使えるようです。

ちなみに Surface Pro X は仮想化に対応しているっぽいので、WSL2 の実行も可能でしょう。

ARM32 (WOW64)

元々 ARM32 だけに対応した Windows 10 PC は存在しないので、UWP で Windows 10 Mobile 向けにビルドされていたバージョンがダウンロード出来るケースぐらいかなと思います。

前述したように ARM32 の場合は CPU のエミュレーションではないので性能は比較的良いです。

Minecraft for Windows 10

何故か Minecraft for Windows 10 は ARM32 向けのビルドが提供されていました。体験版をインストールして試してみましたが、快適に遊べましたし CPU 使用率はかなり低かったです。

f:id:shiba-yan:20191116174210p:plain

ゲームなのでそれなりに GPU は使っていましたが、適当に弄った範囲では処理落ちなどしませんでした。

GPU 周りはオーバーヘッドが少なそうなので、x86 エミュレーションを避けて Direct3D が中心に使われている分には割とゲームは動きそうな気配がしました。ちなみに SQ1 は DirectX FL 11.1 の対応です。

x86 (WOW64 + エミュレーション)

数々のレビューで指摘されているのが x86 のパフォーマンスについてですが、一応 x86 => ARM64 への変換はキャッシュしていたり、それ以外にも最適化を施しているようですが限界があります。

アプリケーションがそもそも正常に動作しない場合は、ファイルのプロパティから互換性設定を弄ることが出来ます。トラブルシューティングツールを使っても良いみたいです。

f:id:shiba-yan:20191116214349p:plain:w450

プリインストールされているアプリケーションは殆どが ARM64 もしくは ARM32 なので、大体はあとからインストールしたアプリケーションが該当します。

Office 365 / OneDrive

Surface Pro X を購入すると最初から Office 365 の体験版が入っていましたが、実体は x86 版の Click-to-Run でした。おそらく ARM64 版がリリースされることは無さそうです。

f:id:shiba-yan:20191116212550p:plain:w600

x86 エミュレーションはオーバーヘッドが大きいですが、Office 系はめちゃくちゃ CPU を使うというわけでもないので、特に問題なく利用できました。この感じでは ARM64 対応はコスパ悪そうです。

iTunes

最近はアップデートが面倒なので Store から入れてますが、x86 に対応してるので問題なく動きます。

f:id:shiba-yan:20191116211012p:plain

ただし、再生時の CPU 使用率がちょっと高いかなーという印象ですが、元々 iTunes は CPU を結構食うだけな気もします。タッチ操作もしにくいし、ちょっと悩むところです。

Electron ベースのアプリ (Slack / Visual Studio Code など)

まだ Slack や Visual Studio Code のベースになっている Electron が ARM64 に対応してないので、x86 エミュレーションで動作しますが ARM64 対応は既に完了しているようです。

同時に Node.js の ARM64 対応も中の人によっていろいろ行われたらしいです。

使われている Electron のバージョンが上がれば、ARM64 に対応されるアプリも出てきそうです。多分 Visual Studio Code は対応が行われる流れだと思います。

.NET Framework ベースのアプリ

最初は ARM64 向けのランタイムが用意されているのかと思っていたのですが、実機で確認すると x86 のランタイムしか入っていなかったので、ARM64 への対応は不可能になりました。

将来的には .NET Core が Windows 10 の ARM64 に対応すると思われるので、そっちに移行しない限り x86 エミュレーションからは逃れられないようです。とても残念です。

長々と書いてきましたが、個人的には Surface Pro X は Always Connected PC かつ ARM64 という面白い石が載っていて長時間稼働が出来、デバイス自体は薄型軽量で狭ベゼルかつファンレスでデザインも良いので気に入っています。実際ハワイまで買いに行って良かったです。

アプリ側の対応ですが Apple のように 64bit 必須に出来れば良いのでしょうが、Surface Pro X がバカ売れしてベンダーが対応せざるを得ないという状態にならないと難しいでしょう。

ハワイに行って検証用に Surface Pro X を買ってきた

ずっと ARM64 な CPU が載った Windows 10 PC が動作検証用に欲しかったので、Surface Pro X の発売予定日に合わせてハワイまで行って買ってきました。

公式ブログや Panos は 11/5 に発売みたいに言ってましたが、実際には 11/6 の午後になるまで在庫は入っていませんでした。発売日に買えないとか印象悪すぎなので MS はマジで改善してほしい。

f:id:shiba-yan:20191106175633j:plain

購入したモデルは 8GB *1 RAM / 128GB SSD の一番安い $999 のやつです。動作検証用なのでメモリや SSD は大して必要なかったので、コスパ重視しました。CPU は同じなので問題ないです。

ちなみに店頭には 8GB モデルしか入荷しないようだったので、16GB はオンライン専売のようです。

持って行っていた Surface Laptop 3 と並べてみました。ベゼルは上側は Laptop 3 とあまり変わらないですが、横側はかなり細くなっているので画面は思ったより広いです。

f:id:shiba-yan:20191106192055j:plain

持った感じはかなり薄くて軽かったので驚きました。実測は分からないですが、感覚的には iPad Pro より Surface Pro X の方が薄く感じました。デカくて薄い板という感じです。

Windows 10 Home が入っていますが、プロダクトキーを入れたら Pro にアップデート出来そうです。

f:id:shiba-yan:20191109085449p:plain:w650

CPU の詳細は定番の CPU-Z や Coreinfo が ARM 系に対応していないので、まともに情報は取れませんでしたが、ARMv8 系で Qualcomm という情報だけは取れました。

f:id:shiba-yan:20191109101229p:plain:w650

海外のレビューだとバッテリーの持ちが悪いという話が出てましたが、思ったより CPU クロックが下がらない印象を持ったので、それが関係している気がします。

発売日に配布されたファームウェアアップデートによって改善された感はあります。ちなみに例によって技適マークはついていないので機内モードで弄っています。

f:id:shiba-yan:20191109094549p:plain:w650

クロックの変動幅は 1GHz ~ 3GHz ぐらいのようなので、Intel みたいに 400MHz まで落ちたりしないみたいです。8 コア載ってますが恐らく big.LITTLE なので、単純に比較はできないでしょう。

メモリ周りは LPDDR4X-2133 なので Laptop 3 のやけくそ LPDDR4X-3733 と比べると差が大きいです。

f:id:shiba-yan:20191109094543p:plain:w550

Surface Laptop 3 もそうでしたが、Surface Pro X もストレージ周りが改善されている感じがあります。持っている Surface Book 2 よりスコアは上回っていました。

f:id:shiba-yan:20191109094534p:plain:w550

NVMe 1.3 対応で基本的には Laptop 3 とほぼ同じスペックのようでした。特に不満はありません。

ARM64 に対応したアプリ・ライブラリを作る

海外のレビューではアプリの互換性周りを死ぬほど突っ込まれてましたが、ARM64 の CPU を乗せた時点でそんなことは分かり切っているので気にしていません。

開発者らしく ARM64 対応を行っていって、ネイティブで動作するようにする方が建設的な発想です。

ちょうど HoloLens 2 の出荷も発表されたので、ARM64 への対応モチベーションは高くなっていくと考えています。アレも中身は Snapdragon 850 なので最適なパフォーマンスを出すには ARM64 が必須のはずです。

既に ARM64 向けにもビルドした UWP アプリケーションを公開していましたが、実機での確認が出来ないのでどうしようもなかったのですが、Surface Pro X を使って問題なく動作することを確認できました。

この UWP アプリケーションの ARM64 対応のために、非対応だったライブラリに対して Pull Request を投げて ARM64 に対応してもらったりもしたので、実機があると貢献もはかどりそうです。

*1:1かずあき

Surface Book 2 から Surface Laptop 3 に乗り換えた

タイトルの通りですが、2 年使っていた Surface Book 2 から Surface Laptop 3 に乗り換えました。購入したのは 13.5" / マットブラック / Core i7 / 16GB RAM*1 / 512GB SSD のモデルです。

アルカンターラは汚れが心配だったので、Laptop 3 から追加されたメタルモデルを選びました。マットブラックは指紋が目立ちやすいと聞いてましたが、今のところ大したことないです。

f:id:shiba-yan:20191023194105j:plain

とにかく Surface Book 2 と比べて軽くて薄くてかっこよいです。そして全体的に Book 2 よりパフォーマンスは上なので快適です。後で紹介しますが、ストレージ周りも良くなっていました。

メタルモデルは放熱という観点でも有利のように感じます。キーボード周りがアルカンターラの Laptop 2 と異なっているように感じましたが、検証はしていません。

Surface Book 2 を買った時にも同じように書いたので、パフォーマンス周りは見比べてください。

Book 2 には dGPU が付いているのが特徴でしたが、自分の使い方では全く dGPU が必要なかったです*2。なので iGPU が強化されている Ice Lake を狙っていました。

USB-C 周り

Ice Lake の iGPU から DisplayPort 1.4a に対応したので、これまで Surface Book 2 などで不可能だった USB-C 経由での給電 / WQHD 2 枚 / USB ハブがケーブル一本で使えるようになりました。

モニターに繋いである USB-C のケーブル 1 本だけで完結するのは最高に便利です。

f:id:shiba-yan:20191023192021j:plain

何回か試しただけですが、この構成の場合は時々 USB-C での給電が認識されないときがあったり、多少の不安定さはありました。ファームウェアやドライバの問題だと思います。

ケーブルを差し直すと大体直ったので、実用上は特に問題ないかなと思っています。

f:id:shiba-yan:20191023223957p:plain

雑スクリーンショットですが、ちゃんと 2 枚の WQHD 画面に出力しつつ給電も行えています。

モニターにあるハブに USB 機器を繋げると、ちゃんと Surface Laptop 3 側で認識されたので完璧です。USB-C での給電用に Anker の GaN なアダプターを買っておきました。

ちなみに Surface Laptop 3 の高速充電は付属の 65W 電源か、USB-C で 60W 以上出るアダプターを使うと有効になるようです。Surface Connect 以外に USB-C でも高速充電が使えるのは便利ですね。

Surface デバイスの高速充電

高速充電のために Surface Laptop 3 / Pro 7 / Pro X のアダプターは 65W になっているようです。

パフォーマンス

搭載されている CPU は定格 1.3GHz のモデルですが、例によって cTDP で 1.5GHz になってました。Visual Studio のインストールなどを行っていましたが、サクッと 3.9GHz まで上がるので不便はしないです。

がっつり環境を作っていましたが、思ったより熱くならないという印象を持ちました。

f:id:shiba-yan:20191023224008p:plain

CPU-Z で見ると、ちゃんと AVX512 と SHA が見えました。あまり使わない気もしますが。

f:id:shiba-yan:20191023224017p:plain

重要なのは Surface Laptop 3 の CPU が Surface Book 2 より速くなっているという点です。発売前からベンチを調べてましたが、低いクロックをひっくり返してちゃんと速くなってます。

メモリも LPDDR4X-3733 というかなり速いやつが積まれていたので満足です。ちなみに海外メディアで書かれていたように、Thunderbolt 3 は無効化されているようでした。

Surface Book 2 は中途半端なパフォーマンスの SSD が積まれていたので不満でしたが、Surface Laptop 3 はなかなか速い SSD でした。東芝製なのが少し気になりましたが。

Book 2 では NVMe 1.0 / 1.1 でしたが、Laptop 3 は NVMe 1.3 に対応していました。

Ice Lake の iGPU はかなりパフォーマンスが向上しているようで、試しに少し前に話題になった 8K 動画のデコードを試してみると、問題なく 8K 60fps でハードウェアデコードされました。

割と地味なアップデートっぽく思ってましたが、かなりパフォーマンスが底上げされた感があります。Visual Studio のインストールや起動も早かったので、開発マシンとして役に立ってくれそうです。

*1:2 かずあき

*2:アプリが対応してないとほぼ使われない残念さだった

Surface Go に内蔵されている NFC を試した

理由は分からないですが、何故か Surface Go には NFC が内蔵されています。しかし、今のところ使い道が無いらしく、本当にチップが載っているだけのようです。

こんな面白そうなチップが付いているのにもったいないと思ったので、UWP に用意されている SmartCard 周りの API を使って読み込みを行ってみます。

NFC 周りのサンプルコードは Microsoft から公式で公開されています。

iFixit の分解レポートやデバイスマネージャーを確認した限りでは NXP P3003 というチップが載っているみたいですが、情報が全くないので実際にいろんなカードをかざしてみるしか方法が無かったです。

f:id:shiba-yan:20181015003356p:plain

とりあえず読み込みだけを試したかったので、非常に雑なコードを書いて Surface Go にデプロイしました。

Visual Studio を Surface Go にはインストールしていないですが、開発者モードにしておくと他の Visual Studio からリモートデバッグ出来るので便利です。

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    var deviceSelector = SmartCardReader.GetDeviceSelector(SmartCardReaderKind.Nfc);

    var devices = await DeviceInformation.FindAllAsync(deviceSelector);

    var device = devices.FirstOrDefault();

    if (device == null)
    {
        return;
    }

    var reader = await SmartCardReader.FromIdAsync(device.Id);

    if (reader == null)
    {
        return;
    }

    reader.CardAdded += Reader_CardAdded;
    reader.CardRemoved += Reader_CardRemoved;
}

private async void Reader_CardAdded(SmartCardReader sender, CardAddedEventArgs args)
{
    await AddLogAsync($"{DateTime.Now} - CardAdded");

    using (var connection = await args.SmartCard.ConnectAsync())
    {
        var iccDetection = new IccDetection(args.SmartCard, connection);

        await iccDetection.DetectCardTypeAync();

        await AddLogAsync($"{DateTime.Now} - CardName = {iccDetection.PcscCardName}");
        await AddLogAsync($"{DateTime.Now} - DeviceClass = {iccDetection.PcscDeviceClass}");
    }
}

private async void Reader_CardRemoved(SmartCardReader sender, CardRemovedEventArgs args)
{
    await AddLogAsync($"{DateTime.Now} - CardRemoved");
}

PC/SC SDK はサンプルコードと同じリポジトリにあったので、それを使いました。

ちなみに NFC のチップが付いている場所が少し分かりにくかったです。画面側からは反応しなかったのでカードを持って探したところ、裏面のカメラ左側あたりにカードを持っていくと読み込むことが出来ました。

今回用意したカードは以下の通りです。仕様的には全部用意できた気がします。

  • マイナンバーカード (NFC-B)
  • Kitaca (NFC-F)
  • e-AMUSEMENT PASS (旧型, NFC-V)
  • Aime (NFC-A)
  • NESiCA (NFC-A)

これらのカードを Surface Go にかざしていきましたが、読み込めたカードは以下の通りです。ぶっちゃけ、かなり予想外の結果となりました。

  • e-AMUSEMENT PASS
  • NESiCA

FeliCa の対応は正直期待していなかったですが、Type B も読み込めず Type A に関しても一部の仕様の場合のみ読み込みが可能でした。このままだと使い道が本気でなさそうです。

実際に読み込んだカードの情報をログを出していたので、それも載せておきます。

f:id:shiba-yan:20181015003405p:plain

NESiCA は MIFARE UltraLight と認識されて、無事に読み込みが出来ました。e-AMUSEMENT PASS は聞きなれない I-CODE SLI として読み込まれました。

せめて FeliCa の非暗号化領域や Type B が読めれば、多少なりとも活用の方法が見つかりそうだったのですが、今の挙動では本気で使い道が無さそうです。ドライバレベルで対応できれば最高なのですが、この感じでは期待できないでしょう。

Surface Go の USB-C ディスプレイ出力を試した

Surface Go をサブノートとして使うために、ディスプレイ出力に関して確認をしておきました。主にプレゼンテーション時に Surface Go を使うことが想像できたのと、USB-C に関してはまだ心配があったので。

公式の技術仕様には外部出力に関する情報が書いていないのはマイナスポイントです。

Surface Go 技術仕様 | Surface

一応 Intel の情報によると HD Graphics 615 は DisplayPort なら 4K 60fps に対応しているらしいです。外部ディスプレイも 2 枚までは出力できるみたいですが、USB-C が 1 つしかないので工夫が必要です。

とりあえず手持ちの機材で確認できる範囲に関しては実際に接続して試しました。Surface Book 2 の時と全く同じ環境とも言います。

DisplayPort

前から持っていた USB-C の Alternate Mode に対応したケーブルを使って、DisplayPort での出力を試しました。結構このケーブルはいい値段がするので悩みますが、スッキリと接続できるのでお勧めです。

ケーブル自体は 4K 60fps に対応していますが、モニターが 4K 非対応なので確認は出来ていません。*1

例によって DisplayPort の MST を使って 2 枚の構成にしてあるので少し特殊かもしれませんが、問題なく Surface Go の USB-C に接続したところトリプルディスプレイを実現できました。

f:id:shiba-yan:20180924210204p:plain

フル HD モニターですが、1 本のケーブルで 2 枚に出力できるのはかなり便利です。

Surface Go 側をドットバイドットで運用しているので、モニターをまたぐときに解像度の変更が走らないのもメリットです。充電は Surface Connect で行ってしまいますが、仕様上はディスプレイ出力しながら充電もできるはずなので試してみたくはあります。

ちなみに Surface Go の発売と同時に USB-C から DisplayPort への変換アダプターが発売されたみたいですが、どこにも情報が見当たらなかったので出力可能な形式などは分からなかったです。

恐らくは 4K 60fps まではいけるのではと思っていますが、かなり謎なアダプターとなっています。

HDMI

USB-C から HDMI への変換アダプターは手持ちの Surface Book 2 用となっている公式のものを使いました。

このアダプターも結構いい値段がしますが、HDMI 2.0 に対応していて 4K 60fps まで安定して出せます。

実際に手持ちの 4K テレビに HDMI で接続して試してみたところ、問題なく 4K 60fps で出力出来ました。しかし 4K で出力すると、少し動作が引っかかる時があるかなという印象です。

f:id:shiba-yan:20180924210214p:plain

ドットバイドットで表示させていたのも原因かもしれませんが、あまり使われないケースだと思います。

4K の動画を再生してみましたが、Book 2 の時と同様に大半はハードウェアで処理されるので、CPU の負荷は比較的低くすんでいました。コマ落ちすることもなく再生されました。

f:id:shiba-yan:20180924210223p:plain

最近のプレゼン環境は接続が HDMI なことが多いので、Book 2 用に勝っておいたアダプターが問題なく使えて安心しました。USB-C があと 1 つあれば汎用性が増したと思うのですが、割と何とかなりそうです。

実際に今週末は Surface Go だけ持ってプレゼンを行おうと思っています。とても楽しみです。

*1:Surface Go の仕様上は DisplayPort で 4K 60fps 出せるはず