# Checking for available system memory

**URL:** <https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669>\
**Category:** Help & Support\
**Created:** [March 5, 2024, 7:34pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669 "2024-03-05T19:34:54Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 5, 2024, 7:34pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/1 "2024-03-05T19:34:54Z")

</div>

What I want to do at runtime is check if there is available system memory to run a program.  
This is running on a Linux system.  
Are there native Crystal resources to do this, or do I need to use native OS commands?  
The simplest possible way is desired.

```auto
def my_cool_program
   needed_memory = compute_needed_memory
   return "insufficient memory" unless sufficient_memory?
   # Do stuff with memory
end

def sufficient_memory? (needed_memory)
  available_memory = # determine available system memory
  available_memory > needed_memory
end

```

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 5, 2024, 8:38pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/2 "2024-03-05T20:38:11Z")

</div>

I know I can run OS commands such as:

```auto
$ free 

$ cat /proc/meminfo

```

but then I have to parse the output to get the available memory info as a numerical value.  
I hope Crystal has a simpler and more direct way to do this.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [March 5, 2024, 8:40pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/3 "2024-03-05T20:40:13Z")

</div>

Looks like there is [GitHub - crystal-community/hardware: Get CPU, Memory and Network informations of the running OS and its processes](https://github.com/crystal-community/hardware), but who knows if it still works.

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [March 5, 2024, 9:24pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/4 "2024-03-05T21:24:05Z")

</div>

I think it would be nice if stdlib could provide some basic system info. Currently, this is not available though.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 5, 2024, 9:27pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/5 "2024-03-05T21:27:21Z")

</div>

A little search of StackOverflow provided this cli solution.

```auto
awk '/Availabe Memory/{print $(NF-3)}' /proc/meminfo

```

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 5, 2024, 9:43pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/6 "2024-03-05T21:43:49Z")

</div>

This a simpler cli variant.

```auto
$ cat /proc/meminfo | grep "MemAvailable"
MemAvailable: 33175076 kB

```

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 5, 2024, 10:23pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/7 "2024-03-05T22:23:10Z")

</div>

After a little trial and error, this works, and returns the KB of available memory.  
You can then convert it to GB, bytes, etc as you need.

```auto
def available_KB
  `cat /proc/meminfo | grep "MemAvailable"`.split(' ')[3].to_i
end

```

You can play around to extract the other `/proc/meminfo` field values.

I think this should be very straightforward to implement for the std::lib, at least for `[Li|U]Nix`.

USED IN CODE:

```auto
def sufficient_memory? (needed_KB_memory)
  avail_KB = `cat /proc/meminfo | grep "MemAvailable"`.split(' ')[3].to_i
  avail_KB > needed_KB_memory
end

```

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 5, 2024, 11:08pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/8 "2024-03-05T23:08:05Z")

</div>

After thinking about it, this allows for a bit more universal usage.

```auto
def available_KB
  `cat /proc/meminfo | grep "MemAvailable"`.split(' ')[3].to_i
end

```

Then in code:

```auto
return "Insufficient Memory" unless available_KB > needed_KB

```

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 6, 2024, 12:28am UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/9 "2024-03-06T00:28:24Z")

</div>

> [@jzakiya](#):
>
> After thinking about it, this allows for a bit more universal usage.
> 
> ```auto
> def available_KB
> `cat /proc/meminfo | grep "MemAvailable"`.split(' ')[3].to_i
> end
> 
> ```

Someone in the Rust forum (where I asked the same question for doing it in Rust) pointed out I can simplify the cli command. Here’s it with the shortened|tested cli command.

```auto
def available_KB
  `grep MemAvailable /proc/meminfo`.split(' ')[3].to_i
end

```

This is not just shorter, and easier to read and follow, and with better symantics.  
It now only uses `grep` (or equivalent) and `/proc/meminfo` as Nix dependencies.  
Crystal already has a `grep` so only the info in `/proc/meminfo` is an external dependency.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 6, 2024, 4:38am UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/10 "2024-03-06T04:38:33Z")

</div>

Here are a couple more `SysMem` methods.  
Put them all in a file on your system and run as follows.

```auto
# SysMemMethods.cr

def available_sys_mem
  `grep MemAvailable /proc/meminfo`.split(' ')[3].to_i
end

def total_sys_mem
  `grep MemTotal /proc/meminfo`.split(' ')[7].to_i
end

def free_sys_mem
  `grep MemFree /proc/meminfo`.split(' ')[8].to_i
end

puts "Available System Memory = #{available_sys_mem} kB"
puts "Total System Memory = #{total_sys_mem} kB"
puts "Free System Memory = #{free_sys_mem} kB"
--------------------------------------------------------

$ cyrstal run SysMemMethods.cr
Available System Memory = 30484736 kB
Total System Memory = 40436388 kB
Free System Memory = 21327500 kB

```

ADDED:  
These are more ubiquitous for these values:

```auto
def available_sys_mem
  `grep MemAvailable /proc/meminfo`.split(' ')[-2].to_i
end

def total_sys_mem
  `grep MemTotal /proc/meminfo`.split(' ')[-2].to_i
end

def free_sys_mem
  `grep MemFree /proc/meminfo`.split(' ')[-2].to_i
end

```

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [March 6, 2024, 10:28am UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/11 "2024-03-06T10:28:54Z")

</div>

Any particular reason for shelling out? You could process `File.read("/proc/meminfo")` directly in Crystal.

---

<div class="post-metadata">

**Author:** ![HertzDevil](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/hertzdevil/32/1023_2.png) [@HertzDevil](https://forum.crystal-lang.org/u/HertzDevil)\
**Post date:** [March 6, 2024, 11:23am UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/12 "2024-03-06T11:23:35Z")

</div>

As a general note, the BSDs prefer using `LibC.sysctl`, because there is no procfs on macOS and OpenBSD.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 6, 2024, 5:15pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/13 "2024-03-06T17:15:03Z")

</div>

Well, I originally asked if there was a native way to do this and wasn’t provided one.  
I knew the information I wanted was available via the shell commands, so that’s what I did.

If you can provide (show) a more native Crystal way to do it that would be nice.

---

<div class="post-metadata">

**Author:** ![Blacksmoke16](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/blacksmoke16/32/1241_2.png) [@Blacksmoke16](https://forum.crystal-lang.org/u/Blacksmoke16)\
**Post date:** [March 6, 2024, 5:30pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/14 "2024-03-06T17:30:58Z")

</div>

> [@jzakiya](#):
>
> If you can provide (show) a more native Crystal way to do it that would be nice.

Prob could just copy what the one shard I linked earlier does. It isn’t system agnostic since it reads the proc file, but doesn’t shell out to anything.

---

<div class="post-metadata">

**Author:** ![Fryguy](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/fryguy/32/1181_2.png) [@Fryguy](https://forum.crystal-lang.org/u/Fryguy)\
**Post date:** [March 12, 2024, 4:57pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/15 "2024-03-12T16:57:49Z")

</div>

On the Ruby side I use djberg96’s sys-\* gems where I need things like this, particularly sys-proctable and sys-memory ([ref](https://github.com/search?q=owner%3Adjberg96+sys&type=repositories)) . These gems are nice because they handle cross-platform against Windows/Mac/Linux. I could see these being used as inspiration for a new shard.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 12, 2024, 9:27pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/16 "2024-03-12T21:27:04Z")

</div>

Basically here’s the Ruby code that captures everything in `/proc/meminfo` in a hash.

```auto
MEMORY_FILE = '/proc/meminfo'
MEMINFO_REGEX = /(.*)?:\s+?(\d+)/.freeze

def memory
  hash = {} 

  File.foreach(MEMORY_FILE) do |line|
    key, value = MEMINFO_REGEX.match(line.chomp).captures
    hash[key] = value.to_i
  end

  hash
end

```

I tried to translate that to Crystal (I hardly know regexs) as:

```auto
def memory_vals
  mem_vals = Hash(String, Int32).new
  File.each_line("/proc/meminfo") do |line|
    #key, value = /(.*)?:\s+?(\d+)/.match(line.chomp)
    key, value = line.match (/(.*)?:\s+?(\d+)/)
    mem_vals[key] = value.to_i
  end
  mem_vals
end

```

But keep getting this error message.

```auto
In availablemem.cr:47:18

 47 | key, value = line.match (/(.*)?:\s+?(\d+)/)
                   ^-
Error: undefined method '[]' for Nil (compile-time type is (Regex::MatchData | Nil))

```

Can someone clean this up.

---

<div class="post-metadata">

**Author:** ![RespiteSage](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/respitesage/32/793_2.png) [@RespiteSage](https://forum.crystal-lang.org/u/RespiteSage)\
**Post date:** [March 13, 2024, 5:01pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/17 "2024-03-13T17:01:30Z")

</div>

`String#match` returns `Regex::MatchData | Nil`: [method documentation](https://crystal-lang.org/api/1.11.2/String.html#match%28regex%3ARegex%2Cpos%3D0%2C%2A%2Coptions%3ARegex%3A%3AMatchOptions%3DRegex%3A%3AMatchOptions%3A%3ANone%29%3ARegex%3A%3AMatchData%7CNil-instance-method)

It’s not a regex issue. You just need to handle the return value of the method correctly.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [March 13, 2024, 6:56pm UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/18 "2024-03-13T18:56:20Z")

</div>

OK, this now works.

```auto
def sys_mem_info
  mem_info = Hash(String, Int64).new
  File.each_line("/proc/meminfo") do |line|
    key, value = line.match(/(.*)?:\s+?(\d+)/).not_nil!.to_s.split
    mem_info[key] = value.to_i64
  end
  mem_info
end

pp sys_mem_info
{"MemTotal:" => 40436388,
 "MemFree:" => 21216224,
 "MemAvailable:" => 30907248,
 "Buffers:" => 2133020,
 "Cached:" => 6075404,
 "SwapCached:" => 0,
 "Active:" => 7332312,
 "Inactive:" => 5907564,
 "Active(anon):" => 5591920,
 "Inactive(anon):" => 0,
 "Active(file):" => 1740392,
 "Inactive(file):" => 5907564,
 "Unevictable:" => 88,
 "Mlocked:" => 88,
 "SwapTotal:" => 4193292,
 "SwapFree:" => 4193292,
 "Zswap:" => 0,
 "Zswapped:" => 0,
 "Dirty:" => 6696,
 "Writeback:" => 0,
 "AnonPages:" => 5031392,
 "Mapped:" => 1139696,
 "Shmem:" => 560640,
 "KReclaimable:" => 2568336,
 "Slab:" => 2735624,
 "SReclaimable:" => 2568336,
 "SUnreclaim:" => 167288,
 "KernelStack:" => 31568,
 "PageTables:" => 69804,
 "SecPageTables:" => 0,
 "NFS_Unstable:" => 0,
 "Bounce:" => 0,
 "WritebackTmp:" => 0,
 "CommitLimit:" => 24411484,
 "Committed_AS:" => 14086608,
 "VmallocTotal:" => 34359738367,
 "VmallocUsed:" => 106140,
 "VmallocChunk:" => 0,
 "Percpu:" => 7040,
 "HardwareCorrupted:" => 0,
 "AnonHugePages:" => 0,
 "ShmemHugePages:" => 0,
 "ShmemPmdMapped:" => 0,
 "FileHugePages:" => 0,
 "FilePmdMapped:" => 0,
 "CmaTotal:" => 0,
 "CmaFree:" => 0,
 "HugePages_Total:" => 0,
 "HugePages_Free:" => 0,
 "HugePages_Rsvd:" => 0,
 "HugePages_Surp:" => 0,
 "Hugepagesize:" => 2048,
 "Hugetlb:" => 0,
 "DirectMap4k:" => 3312512,
 "DirectMap2M:" => 15945728,
 "DirectMap1G:" => 23068672}

```

So now you get everything in `/proc/meminfo`, and can do (values for my system):

```auto
meminfo = sys_mem_info

puts "Total Memory = #{meminfo["MemTotal:"].format} KB" # => 40,436,388 KB

puts "Swap Memory = #{meminfo["SwapTotal:"].format} KB" # => 4,193,292 KB

```

---

<div class="post-metadata">

**Author:** ![lemmuh](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/lemmuh/32/2236_2.png) [@lemmuh](https://forum.crystal-lang.org/u/lemmuh)\
**Post date:** [March 27, 2024, 9:17am UTC](https://forum.crystal-lang.org/t/checking-for-available-system-memory/6669/19 "2024-03-27T09:17:05Z")

</div>

Just for completeness, for windows it can done like this:

```auto
  lib LibKernel32
    struct MemoryStatusEx
      length : UInt32
      memory_load : UInt32
      total_phys : UInt64
      avail_phys : UInt64
      total_page_file : UInt64
      avail_page_file : UInt64
      total_virtual : UInt64
      avail_virtual : UInt64
      avail_extended_virtual : UInt64
    end

    fun GlobalMemoryStatusEx(lpbuffer : MemoryStatusEx*) : LibC::BOOL
  end

  memory_status_ex = LibKernel32::MemoryStatusEx.new
  memory_status_ex.length = sizeof(LibKernel32::MemoryStatusEx)
  LibKernel32.GlobalMemoryStatusEx(pointerof(memory_status_ex))

  memory_system_available = memory_status_ex.avail_phys
  memory_system_total = memory_status_ex.total_phys

```
