Closed4

TinyGo で メモリの使いすぎによるエラーが出た際の対処法をまとめる

ehime-iyokanehime-iyokan

現象:TinyGo のプログラムをマイコンボードに書き込み、動かした結果、以下のエラーが発生した。
panic: runtime error at 0x????????: out of memory
[tinygo: panic at *.go:??:??]
(?→数値、*→文字列)

ehime-iyokanehime-iyokan

対処1:大きなデータを格納する際、バッファとしてスライスを使用している場合は global 変数の配列を使用するようにする。
ループ内でスライスを定義している場合などでは、都度メモリが割り当てられ、Heap に積まれるため。
補足:tinygo buildコマンドで--print-allocs . を付けて実行すると heap allocs している個所の一覧が表示されるため、該当箇所を減らすと良さそう。

ehime-iyokanehime-iyokan

対処2:大きなデータを扱う場合は、そもそも必要なデータだけ扱うようにする。
以下、例。

  • 自分が使っていた API(Open Weather API 3.0) では 不要な情報を省くパラメーターを指定することができる。
  • API から JSON データを取得して Unmarshal する場合、データを受け取る構造体のメンバ変数はすべてのデータ分を定義する必要はないため、減らすことを検討する
デフォルトの構造体
type AutoGenerated struct {
	Lat            float64 `json:"lat"`
	Lon            float64 `json:"lon"`
	Timezone       string  `json:"timezone"`
	TimezoneOffset int     `json:"timezone_offset"`
	Hourly         []struct {
		Dt         int     `json:"dt"`
		Temp       float64 `json:"temp"`
		FeelsLike  float64 `json:"feels_like"`
		Pressure   int     `json:"pressure"`
		Humidity   int     `json:"humidity"`
		DewPoint   float64 `json:"dew_point"`
		Uvi        int     `json:"uvi"`
		Clouds     int     `json:"clouds"`
		Visibility int     `json:"visibility"`
		WindSpeed  int     `json:"wind_speed"`
		WindDeg    int     `json:"wind_deg"`
		WindGust   float64 `json:"wind_gust"`
		Weather    []struct {
			ID          int    `json:"id"`
			Main        string `json:"main"`
			Description string `json:"description"`
			Icon        string `json:"icon"`
		} `json:"weather"`
		Pop  float64 `json:"pop"`
		Rain struct {
			OneH float64 `json:"1h"`
		} `json:"rain,omitempty"`
	} `json:"hourly"`
}
変更後の構造体
// 不要なデータは削除。Hourly はデフォルトで 48h 分取得してしまうが 6h 分に限定した。
type WeatherJSON struct {
	Timezone       string `json:"timezone"`
	TimezoneOffset int    `json:"timezone_offset"`
	Hourly         [6]struct {
		Dt      int `json:"dt"`
		Weather []struct {
			Icon string `json:"icon"`
		} `json:"weather"`
	} `json:"hourly"`
}
このスクラップは1ヶ月前にクローズされました