Coder Social home page Coder Social logo

oomd's Introduction

oomd

Support Ukraine CI

oomd is userspace Out-Of-Memory (OOM) killer for linux systems.

Background

Out of memory killing has historically happened inside kernel space. On a memory overcommitted linux system, malloc(2) and friends usually never fail. However, if an application dereferences the returned pointer and the system has run out of physical memory, the linux kernel is forced to take extreme measures, up to and including killing processes. This is sometimes a slow and painful process because the kernel can spend an unbounded amount of time swapping in and out pages and evicting the page cache. Furthermore, configuring policy is not very flexible while being somewhat complicated.

oomd aims to solve this problem in userspace. oomd leverages PSI and cgroupv2 to monitor a system holistically. oomd then takes corrective action in userspace before an OOM occurs in kernel space. Corrective action is configured via a flexible plugin system, in which custom code can be written. By default, this involves killing offending processes. This enables an unparalleled level of flexibility where each workload can have custom protection rules. Furthermore, time spent livelocked in kernelspace is minimized. In practice at Facebook, we've regularly seen 30 minute host lockups go away entirely.

Installing on Debian 11+ or Ubuntu 20.04+

# apt install oomd

Installing from RPMs on Fedora

oomd is packaged in Fedora as of Fedora 32 and can be installed with:

$ sudo dnf install oomd

Finally, enable and start it with:

$ sudo systemctl enable --now oomd.service

Building from source

Note that oomd requires PSI to function. This kernel feature has been merged into the 4.20 release.

oomd currently depends on meson and jsoncpp. libsystemd is an optional dependency.

oomd also requires GCC 8+ or clang 6+. Other compilers have not been tested.

$ git clone https://github.com/facebookincubator/oomd
$ cd oomd/oomd
$ meson build && ninja -C build
$ cd build && sudo ninja install

Configuration

See docs/configuration.md for a high level overview and some examples.

See docs/core_plugins.md for a quick reference on core plugin capabilities.

See docs/production_setup.md for guidelines on how oomd should be set up in a production environment.

Running tests

oomd depends on gtest/gmock to run tests. Installing gtest/gmock from master is preferred.

If meson detects gtest/gmock is installed, meson will generate build rules for tests.

$ cd oomd
$ rm -rf build
$ meson build && ninja test -C build

Writing custom plugins

It is both possible and encouraged to write custom plugins. The codebase is designed to make writing plugins as easy as possible.

See docs/writing_a_plugin.md for a tutorial.

Help / Discussion / Support

Join our #oomd channel on irc.freenode.net!

License

oomd is GPL 2 licensed, as found in the LICENSE file.

oomd's People

Contributors

abulimov avatar andrew880 avatar c-odrin avatar cdown avatar danobi avatar davide125 avatar dmitryvinn avatar dschatzberg avatar eapolinario avatar filbranden avatar htejun avatar jaredp avatar lnyng avatar manuel-domke avatar manuelhuber avatar mokomull avatar nicoulaj avatar orvid avatar r-barnes avatar san45 avatar slysteven avatar stanislavglebik avatar suraneti avatar tbelagod avatar tconnally avatar void001 avatar yangfl avatar yfeldblum avatar zertosh avatar zpao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

oomd's Issues

memleaks ???

Each time a detection group/action fires, oomd RSS mem usage (/sys/fs/cgroup/system.slice/oomd.service/memory.current) rises in my test environment ~ 400..500 KiB. Are there any mem leaks?

Packaging for Fedora

Fedora Rawhide is ready to oomd packaging. Cgroup2 is used by default and swapaccount is enabled by default.

A few improvements to build definition files

The meson.build file has a couple of common antipatterns. Fixing them would reduce the amount of code and make it more portable and "mesonic" for lack of a better term.

The system adds . as an include path. This is not necessary as in Meson the current source and build dirs are always added to the include path.

Setting the C++ version should not be done with custom args, but instead by setting the language standard option. Most projects do it with something like default_options: ['cpp_std=c++14'] kwarg in the project call.

Adding -g should not be needed. There is a toggle option and it is enabled automatically in debug and debugoptimized build types (the former is the default one).

Instead of adding the -rdynamic flag you should set the export_dynamic kwarg in the executable target.

Instead of copying the fixture data to the build dir you might consider passing a command line argument to the test program to tell it to use the data from the source dir (usually using something like meson.current_source_dir()).

prekill_hooks to run a shell script

I might just be missing something obvious but the documents don't seem to have an example of hooking a bash script using prekill_hooks. I'm wondering if that is possible or something that can be added because it would add a bunch of flexibility.

My use case:

  • a university managing large shared multi user servers
  • often users have code that'll try and eat up all the memory I kill'em off when near 90% of memory

What I hope to do with oomd is catch that out of control PID or process group and use prekill_hooks to pass that information to a bash script to metric/inform admins and the user before oomd does it's magic making it hard to track down details of what was running.

In the script I would then using stdin or args find out the username and send them an email along with a simple grep of ps -aux | grep <PID?> so they know some details on what got killed.

Add interface to pressure_above and pressure_rising_beyond for root host pressure monitoring

It would be nice if pressure_above and pressure_rising_beyond plugins were able to monitor root host pressure.

Interface:

  • root host is encoded by '/'. ie cgroup=/ as the arg for the plugins

Code changes:

  • In PressureAbove::run and PressureRisingBeyond::run, during cgroup wildcard resolution, if the unresolved cgroup == '/', insert '/' into the list of resolved cgroups. Then special case Fs::readMempressure and Fs::readIopressure to pass /proc/pressure/memory and /proc/pressure/io, respectively, to Fs::readRespressure
    • Make sure to handle /proc/mempressure (no IO pressure for 4.11 kernels, though)

Output spam: [../util/Fs.cpp:224] Unable to open ../memory.stat

Oomd works with output spam:

[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/memory.pressure/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/cpu.stat/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/memory.high/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/memory.current/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/cgroup.controllers/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/memory.events/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/cgroup.threads/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/memory.swap.current/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/cgroup.max.descendants/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/cgroup.controllers/memory.stat
[../util/Fs.cpp:224] Unable to open /sys/fs/cgroup/system.slice/memory.swap.events/memory.stat

Full output: http://okturing.com/src/6737/body

Latest oomd on Ubuntu 19.04.

Allow plugins to be written in C

Currently it looks like the only way to write plugins is to write them in c++.

Allowing plugins to be written in C opens up a lot of possibilities - not just C, but any language that can create C-ABI compatible stuff can be used for writing the plugin, and that list is huge compared to just C++. As I understand it, C++ has no well defined ABI which makes it hard to interface with it from any other language.

And since oomd calls the plugins rather than the other way around, it is not possible to simply "wrap" oomd either.

I understand that there might be limitations (I'm mostly thinking macros, and converting types) that make this non-trivial. However, is it possible? If yes, what needs to be done?

--version

Please add -v and --version flags.

High CPU usage

oomd uses about 6% CPU whith desktop.json and --interval 1.

Is it OK?

Add a config checker cmd line option

oomd configs are first parsed and then compiled. If the config is invalid, oomd currently crashes. This is fine-ish but also suboptimal. It would be nice if users could run oomd --check /my/config/file and oomd would exit 0 on "good" config and exit non-zero on "bad" config, along with the relevant error messages.

Oomd::Config2::compile does all the error checking. You'll probably want to look to make changes in Main.cpp and Oomd.cpp.

Pull --cgroup-fs default from /proc/mounts

Instead of setting the default to be /sys/fs/cgroup, it would be better to figure out the cgroup2 mount point from /proc/mounts/.

If cgroup2 is not mounted, we can fail with a helpful error message.

Native dependency 'libfolly' not found

I'm trying to build and test oomd on Debian Stretch but struggling with the libfolly dependency.

I built and installed libfolly with:

  mkdir _build && cd _build
  cmake configure ..
  make -j $(nproc)
  make install

This installed libfolly as a static library into /usr/local.

Now following the oomd build instructions, meson build fails with:

The Meson build system
Version: 0.44.0
Source dir: /sysroot/home/dsd/oomd
Build dir: /sysroot/home/dsd/oomd/build
Build type: native build
Project name: oomd
Native C++ compiler: c++ (gcc 6.3.0)
Build machine cpu family: x86_64
Build machine cpu: x86_64
Found pkg-config: /usr/bin/pkg-config (0.29)

Meson encountered an error in file meson.build, line 43, column 0:
Native dependency 'libfolly' not found

I added -DCMAKE_INSTALL_PREFIX:PATH=/usr to the libfolly build so that it goes straight into /usr, but that didn't change anything. I tried adding -DBUILD_SHARED_LIBS=y to the folly build too, in case oomd wasn't happy about it only installing a static library, but now libfolly build fails with:

/usr/bin/ld: CMakeFiles/folly_base.dir/folly/Random.cpp.o: relocation R_X86_64_TPOFF32 against `_ZZN5folly20SingletonThreadLocalINS_12_GLOBAL__N_120BufferedRandomDeviceENS1_9RandomTagENS_6detail11DefaultMakeIS2_EES3_E3getEvE5cache' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/Singleton.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly18threadlocal_detail10StaticMetaIvvE18getThreadEntrySlowEvE20threadEntrySingleton' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/concurrency/CacheLocality.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZN5folly18SequentialThreadIdISt6atomicE9currentIdE' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/detail/MemoryIdler.cpp.o: relocation R_X86_64_TPOFF32 against `_ZN5folly6detailL13tls_stackSizeE' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/detail/ThreadLocalDetail.cpp.o: relocation R_X86_64_TPOFF32 against `_ZZN5folly18threadlocal_detail14StaticMetaBase18getThreadEntryListEvE24threadEntryListSingleton' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/executors/GlobalExecutor.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly18threadlocal_detail10StaticMetaINS_10TLRefCountEvE3getEPNS0_14StaticMetaBase7EntryIDEE8capacity' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/executors/GlobalThreadPoolList.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly18threadlocal_detail10StaticMetaIvvE3getEPNS0_14StaticMetaBase7EntryIDEE8capacity' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/executors/IOThreadPoolExecutor.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly18threadlocal_detail10StaticMetaIvvE3getEPNS0_14StaticMetaBase7EntryIDEE8capacity' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/executors/QueuedImmediateExecutor.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly18threadlocal_detail10StaticMetaIvvE3getEPNS0_14StaticMetaBase7EntryIDEE8capacity' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/executors/ThreadPoolExecutor.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly18threadlocal_detail10StaticMetaIvvE3getEPNS0_14StaticMetaBase7EntryIDEE8capacity' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/executors/TimedDrivableExecutor.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly20SingletonThreadLocalINS_9hazptr_tcISt6atomicEEvNS_6detail11DefaultMakeIS3_EEvE3getEvE5cache' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/experimental/observer/detail/ObserverManager.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZN5folly15observer_detail15ObserverManager16inManagerThread_E' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/fibers/FiberManager.cpp.o: relocation R_X86_64_TPOFF32 against `_ZZN5folly20SingletonThreadLocalINS_6fibers12_GLOBAL__N_126ScopedAlternateSignalStackENS_6detail10DefaultTagENS4_11DefaultMakeIS3_EEvE3getEvE5cache' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/fibers/FiberManagerMap.cpp.o: relocation R_X86_64_TPOFF32 against `_ZZN5folly18threadlocal_detail10StaticMetaINS_6fibers12_GLOBAL__N_116ThreadLocalCacheINS_9EventBaseEE19ThreadLocalCacheTagEvE3getEPNS0_14StaticMetaBase7EntryIDEE8capacity' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/io/async/EventBaseManager.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly18threadlocal_detail10StaticMetaIvvE3getEPNS0_14StaticMetaBase7EntryIDEE8capacity' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/io/async/Request.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly20SingletonThreadLocalISt10shared_ptrINS_14RequestContextEENS_6detail10DefaultTagENS4_11DefaultMakeIS3_EEvE3getEvE5cache' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/memory/ThreadCachedArena.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZZN5folly18threadlocal_detail10StaticMetaINS_17ThreadCachedArena17ThreadLocalPtrTagEvE3getEPNS0_14StaticMetaBase7EntryIDEE8capacity' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/stats/QuantileEstimator.cpp.o: relocation R_X86_64_TPOFF32 against `_ZN5folly6detailL21tls_lastCpuBufferSlotE' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/synchronization/Rcu.cpp.o: relocation R_X86_64_TPOFF32 against symbol `_ZN5folly6detail16ThreadCachedIntsINS_6RcuTagEE10int_cache_E' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: CMakeFiles/folly_base.dir/folly/ClockGettimeWrappers.cpp.o: relocation R_X86_64_PC32 against symbol `_ZN5folly6chrono13clock_gettimeE' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Bad value
collect2: error: ld returned 1 exit status
CMakeFiles/folly.dir/build.make:516: recipe for target 'libfolly.so' failed

Looking closer, the line in oomd's meson.build that is failing is deps = [dependency('libfolly'),
The meson manual shows that dependency() will use pkg-config, and maybe fall back on other methods, but the build log suggests that it's failing right after pkg-config fails. I modified it to say dependency('libfolly', static : true) but no change. libfolly does have a libfolly.pc.in in the source tree but I can't figure out how to make it generate and install the corresponding .pc file.

How do I set oomd to kill process instead of cgroup?

I'm running oomd on ubuntu 19.10 with default configuration, except that I changed "user pressure above 60 for 30s", to

                        "name": "pressure_above",
                        "args": {
                            "cgroup": "user.slice",
                            "resource": "memory",
                            "threshold": "5",
                            "duration": "5"
                        }

so that I can trigger it more easily using stress, then when I trigger it, this happens:

Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/plugins/PressureAbove.cpp:132] 10s pressure 7.08 is over the threshold of 5 for 5 seconds , total usage is 7345MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/engine/Ruleset.cpp:97] DetectorGroup=user pressure above 60 for 30s has fired for Ruleset=user session protection. Running action chain.
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/engine/Ruleset.cpp:112] Running Action=kill_by_memory_size_or_growth
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:128] Dumping OomdContext:
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:150] name=user.slice/user-1000.slice/session-12.scope
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:151]   pressure=7.09:2.07:0.46-20.19:5.64:1.4
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:156]   mem=7295MB mem_avg=7123MB mem_low=0MB mem_min=0MB mem_high=8796093022207MB mem_high_tmp=0MB mem_max=8796093022207MB mem_prot=0MB anon=6804MB swap_usage=0MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:166]   io_cost_cumulative=0 io_cost_rate=0
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:150] name=system.slice/sddm.service
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:151]   pressure=1.67:0.53:0.18-6.09:1.87:0.67
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:156]   mem=25MB mem_avg=29MB mem_low=0MB mem_min=0MB mem_high=8796093022207MB mem_high_tmp=0MB mem_max=8796093022207MB mem_prot=0MB anon=6MB swap_usage=0MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:166]   io_cost_cumulative=0 io_cost_rate=0
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:150] name=system.slice/systemd-udevd.service
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:151]   pressure=0.39:0.11:0.02-1.88:0.57:0.19
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:156]   mem=12MB mem_avg=12MB mem_low=0MB mem_min=0MB mem_high=8796093022207MB mem_high_tmp=0MB mem_max=8796093022207MB mem_prot=0MB anon=0MB swap_usage=0MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:166]   io_cost_cumulative=0 io_cost_rate=0
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:150] name=system.slice/systemd-journald.service
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:151]   pressure=0.29:0.08:0.01-1.53:0.46:0.16
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:156]   mem=8MB mem_avg=8MB mem_low=0MB mem_min=0MB mem_high=8796093022207MB mem_high_tmp=0MB mem_max=8796093022207MB mem_prot=0MB anon=0MB swap_usage=0MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:166]   io_cost_cumulative=0 io_cost_rate=0
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:150] name=user.slice/user-1000.slice/[email protected]/dbus.service
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:151]   pressure=0.39:0.11:0.02-1.54:0.45:0.15
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:156]   mem=7MB mem_avg=8MB mem_low=0MB mem_min=0MB mem_high=8796093022207MB mem_high_tmp=0MB mem_max=8796093022207MB mem_prot=0MB anon=0MB swap_usage=0MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:166]   io_cost_cumulative=0 io_cost_rate=0
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:150] name=system.slice/oomd.service
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:151]   pressure=1.23:0.33:0.07-3.17:0.82:0.18
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:156]   mem=5MB mem_avg=5MB mem_low=64MB mem_min=0MB mem_high=8796093022207MB mem_high_tmp=0MB mem_max=8796093022207MB mem_prot=0MB anon=0MB swap_usage=0MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:166]   io_cost_cumulative=0 io_cost_rate=0
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:150] name=system.slice/accounts-daemon.service
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:151]   pressure=0.64:0.17:0.04-1.15:0.33:0.1
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:156]   mem=2MB mem_avg=2MB mem_low=0MB mem_min=0MB mem_high=8796093022207MB mem_high_tmp=0MB mem_max=8796093022207MB mem_prot=0MB anon=0MB swap_usage=0MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:166]   io_cost_cumulative=0 io_cost_rate=0
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:150] name=system.slice/rsyslog.service
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:151]   pressure=0.29:0.08:0.01-1.38:0.38:0.08
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:156]   mem=1MB mem_avg=1MB mem_low=0MB mem_min=0MB mem_high=8796093022207MB mem_high_tmp=0MB mem_max=8796093022207MB mem_prot=0MB anon=0MB swap_usage=0MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/OomdContext.cpp:166]   io_cost_cumulative=0 io_cost_rate=0
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/plugins/KillMemoryGrowth-inl.h:163] Picked "user.slice/user-1000.slice/session-12.scope" (7295MB) based on size > 50% of total 7425MB
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/plugins/BaseKillPlugin.cpp:101] Trying to kill /sys/fs/cgroup/user.slice/user-1000.slice/session-12.scope
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/plugins/BaseKillPlugin.cpp:206] Set xattr trusted.oomd_kill_uuid=d7382f70a83ec2e3d923d63cd1a6b73e on /sys/fs/cgroup/user.slice/user-1000.slice/session-12.scope
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/plugins/BaseKillPlugin.cpp:184] Set xattr trusted.oomd_ooms=1 on /sys/fs/cgroup/user.slice/user-1000.slice/session-12.scope
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/plugins/BaseKillPlugin.cpp:147] Killed 20: 13468(sddm-helper) 13472(kwalletd5) 13473(startkde) 13521(ssh-agent) 13551(start_kdeinit) 13553(kdeinit5) 13554(klauncher) 13569(kded5) 13578(kaccess) 13601(kwrapper5) 13605(ksmserver) 13614(kwin_x11) 13619(baloo_file) 13621(krunner) 13624(plasmashell) 13630(polkit-k
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/plugins/BaseKillPlugin.cpp:147] Killed 20: 13666(okular) 13690(okular) 13693(firefox) 13782(at-spi-bus-laun) 13784(agent) 13790(dbus-daemon) 13798(org_kde_powerde) 13908(desktop.so) 13914(file.so) 13949(Web Content) 14006(Web Content) 14026(WebExtensions) 14048(file.so) 14105(plasma-browser-) 14112(Web Conten
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/plugins/BaseKillPlugin.cpp:147] Killed 8: 14395(Web Content) 14432(Web Content) 14551(Web Content) 14665(konsole) 14680(fish) 14737(stress) 14738(stress) 14766(journalctl)
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/plugins/BaseKillPlugin.cpp:197] Set xattr trusted.oomd_kill=48 on /sys/fs/cgroup/user.slice/user-1000.slice/session-12.scope
Apr 12 20:40:03 seireitei oomd[14628]: [../src/oomd/Log.cpp:113] 7.09 2.07 0.46 user.slice/user-1000.slice/session-12.scope 7650164736 ruleset:[user session protection] detectorgroup:[user pressure above 60 for 30s] killer:kill_by_memory_size_or_growth v2
Apr 12 20:40:33 seireitei oomd[14628]: [../src/oomd/engine/Ruleset.cpp:134] Action=kill_by_memory_size_or_growth returned STOP. Terminating action chain.

It kills everything in user cgroup, killing my desktop. Is there a way to set it up so it only kills the process with highest memory usage?

Unable to build the oomd binary

Hi, all , I'm sure that I've setup the jsoncpp and ninja, but when I run 'meson build && ninja -C build'

[root@bogon oomd]# meson build && ninja -C build
The Meson build system
Version: 0.47.2
Source dir: /home/ufo/oomd
Build dir: /home/ufo/oomd/build
Build type: native build
Project name: oomd
Project version: 0.1.0
Native C++ compiler: c++ (gcc 4.8.5 "c++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16)")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Found pkg-config: /usr/bin/pkg-config (0.27.1)

meson.build:72:0: ERROR: Native dependency 'jsoncpp' not found

A full log can be found at /home/ufo/oomd/build/meson-logs/meson-log.txt

[root@bogon ~]# uname -r
5.0.0-rc1+
[root@bogon ~]# cat /etc/redhat-release
CentOS Linux release 7.2.1511 (Core)
[root@bogon ~]# gcc --version
gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-16)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Figure out how to make installed binary name 'oomd'

oomd is currently installed as /usr/local/bin/oomd_bin. This is because there must be a oomd directory in the build directory. The tests are wired to look in ./oomd/fixtures/... because of a FB tooling limitation. Therefore, the binary executable was renamed to oomd_bin.

There has to be a way to change the name of the installed binary. I'm not sure running a script and renaming the binary is a good idea because then ninja uninstall might not clean up everything.

error: call to ‘__open_missing_mode’ declared with attribute error: open with O_CREAT or O_TMPFILE...

I try to compile but it fails.

FAILED: liboomd.a.p/src_oomd_Log.cpp.o
c++ -Iliboomd.a.p -I. -I.. -I../src -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -std=c++17 -g -march=x86-64 -mtune=generic -O2 -fno-plt -D_FORTIFY_SOURCE=2 -fPIC -pthread -DMESON_BUILD -MD -MQ liboomd.a.p/src_oomd_Log.cpp.o -MF liboomd.a.p/src_oomd_Log.cpp.o.d -o liboomd.a.p/src_oomd_Log.cpp.o -c ../src/oomd/Log.cpp
In file included from /usr/include/fcntl.h:329,
                 from ../src/oomd/Log.cpp:20:
In function ‘int open(const char*, int, ...)’,
    inlined from ‘static bool Oomd::Log::init(const string&)’ at ../src/oomd/Log.cpp:76:23:
/usr/include/bits/fcntl2.h:50:24: error: call to ‘__open_missing_mode’ declared with attribute error: open with O_CREAT or O_TMPFILE in second argument needs 3 arguments
   50 |    __open_missing_mode ();
      |    ~~~~~~~~~~~~~~~~~~~~^~
[10/48] Compiling C++ object liboomd.a.p/src_oomd_config_ConfigCompiler.cpp.o

Integration with Nagios, Zabbix etc

How to integrate oomd with monitoring systems? Are there add-ons for collecting metrics from oomd for these systems? I think it would be useful to track oomd events using centralized monitoring systems for owners of large server infrastructure.

oomd should respect OOMScore

Currently oomd also kill processes or groups which have an OOMScore of -1000. It would be nice to ignore those. Another possibility would be to define cgroups which should be ignored.

Have Fs::readDir() lstat instead of use d_type

According to man 3 readdir, d_type is not supported on all filesystems. It turns out XFS is one of those unsupported filesystems.

Instead of if (dir->d_type == DT_REG) { ... }, there should probably be another lstat call.

Build warnings

$ meson build && ninja -C build
The Meson build system
Version: 0.49.0
Source dir: /home/user/1/oomd
Build dir: /home/user/1/oomd/build
Build type: native build
Project name: oomd
Project version: 0.1.0
Native C++ compiler: c++ (gcc 8.3.0 "c++ (Ubuntu 8.3.0-6ubuntu1) 8.3.0")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Found pkg-config: /usr/bin/pkg-config (0.29.1)
Dependency jsoncpp found: YES 1.7.4
Dependency threads found: YES 
Found CMake: /usr/bin/cmake (3.13.4)
Dependency libsystemd found: NO (tried pkgconfig and cmake)
Dependency GTest found: NO (tried pkgconfig and system)
Dependency GMock found: NO (tried pkgconfig and system)
Build targets in project: 2
Found ninja-1.8.2 at /usr/bin/ninja
ninja: Entering directory `build'
[3/33] Compiling C++ object 'oomd@sha/Oomd.cpp.o'.
../Oomd.cpp: In member function ‘void Oomd::Oomd::processDropInAdd(const string&)’:
../Oomd.cpp:434:21: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::unique_ptr<Oomd::Engine::Ruleset> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
   for (int i = 0; i < unit->rulesets.size(); ++i) {
                   ~~^~~~~~~~~~~~~~~~~~~~~~~
[21/33] Compiling C++ object 'oomd@sha/util_Fs.cpp.o'.
../util/Fs.cpp: In static member function ‘static Oomd::ResourcePressure Oomd::Fs::readRespressure(const string&, Oomd::Fs::PressureType)’:
../util/Fs.cpp:356:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
[33/33] Linking target oomd_bin.

Is it OK?

Ubuntu 19.04

KillMemoryGrowth-inl.h: misleading ologKillTarget message for SIZE_NO_THRESHOLD

For analysis it is important to know, why and which cgroup got killed. In case of SIZE_NO_THRESHOLD it is misleading, not clear for anybody, which hasn't read and understood the source code. E.g.:

Picked "lxc.payload.n04-02/user.slice/user-6666.slice/session-4376.scope" (98499MB) based on size > 50% of total 253210MB (size threshold overridden) with kill preference NORMAL
vs.
Picked "lxc.payload.n04-00/user.slice/user-6666.slice/session-4377.scope" (188119MB) based on size > 50% of total 253244MB with kill preference NORMAL

Actually, even the of total ... MiB part is misleading, because the total memory of the system has no impact at all on the decision made - but many users think of MemTotal from /proc/meminfo when they ready total memory (at least non-native speakers ;-)).

So how about removing the total from the phase 1 message, replacing phase 3 message with something like Picked "lxc.payload.n04-00/user.slice/user-6666.slice/session-4429.scope" (187622MiB) based on effective usage of 122086 MiB with kill preference NORMAL (memory.low = 64GiB, mem_adj = 0, mem_scale = 1), and last but not least using the correct unit, i.e. MiB instead of MB?

oomd breaks in case of missing memory controller

While oom prints:

[../Oomd.cpp:182] WARNING: cgroup memory controller not enabled on /sys/fs/cgroup/systemcritical.slice/zabbix-agent.service. oomd will ignore it.

it does not seem to ignore it:

[../util/Fs.cpp:162] Unable to open /sys/fs/cgroup/systemcritical.slice/zabbix-agent.service/memory.current
[../Oomd.cpp:518] Caught bad_control_file: /sys/fs/cgroup/systemcritical.slice/zabbix-agent.service: missing file

oomd crashes at that point

Possibility to abstract the stat collector

Hi, we are running kernel 4.5 now which does not have PSI. Any plan to abstract this part to be configurable instead of having to read stat from the PSI output?

Thanks!

Inefficient TryToKillSomething(): ranking gets made twice for a single run

Right now TryToKillSomething() seems to be very inefficient, because for a single evaluation ranking functions get called twice and including calculation of current overall memory usage (3 times). There should probably be an opaque structure containing the related information (e.g. wrt. src/oomd/plugins/KillMemoryGrowth-inl.h: KMGPhase, sum_current_mem_cgroups, sum_effective_mem_cgroups), which one may pass to ologKillTarget(), and thus eliminates the need to do all the ranking/wasting resources again just for logging ...

gcc-6: is no longer supported since commit: 4b9f45bb

Until Commit 4b9f45b i was able to build oomd on current debian stretch using gcc-6.

Now i get the following errors:

In file included from ../config/ConfigCompiler.cpp:17:0:
../../oomd/config/ConfigCompiler.h:20:20: fatal error: optional: No such file or directory
 #include <optional>
                    ^
compilation terminated.

In file included from ../Oomd.cpp:38:0:
../../oomd/config/ConfigCompiler.h:20:20: fatal error: optional: No such file or directory
 #include <optional>
                    ^
compilation terminated.

I'm afraid that PSI measurements are totally off either due to a kernel bug or MuQSS.

Hi! See hakavlad/nohang#25 (comment) and below:

A bug with the current PSI is that it solely relies on it to kill/terminate processes.
It killed bees (btrfs dedup) while the memory & swap was mostly free.
nohang should check if memory is increasing or if available memory is low.
Memory pressure probably happened because I was compiling a new kernel.
Also, I use muqss scheduler with high frequency timer (1000HZ).

due to muqss kernel I am not sure that psi of memory is measured correctly.
It can stay high for many minutes although processes are idle.

The solution that I propose is that when PSI monitoring is activated, please check also that there is a lack of memory before killing. If no lack of free swap/memory, ignore the high PSI usage.

I executed the program and it indeed caused high PSI. (nohang PSI is still disabled)
I killed it and I now monitor PSI. it is still very high after 10 minutes:
some avg10=99.00 avg60=99.00 avg300=90.78 total=725036638
So I'm afraid that PSI measurements are totally off either due to a kernel bug or MuQSS.

Could you comment this, please?

SIGABRT on launch, no backtrace

Thanks for removing the libfolly dependency that caused me trouble before.

Looking again now, I'm trying to get it working on Debian with systemd-239. The build and install went OK. On first launnch of oomd_bin it segfaulted (with no other error that I could see) and some tracing with gdb indicated that it was because I need to put a config file in place, so I added /etc/oomd.json

{
    "cgroups": [
        {
            "target": "system.slice",
            "oomdetector": "default",
            "oomkiller": "default"
        }
    ],
    "version": "0.2.0"
}

With that in place, it aborts with no logged error. Looking in the source code and with gdb I decided that it was because the memory controller was not active. I set DefaultMemoryAccounting=yes in /etc/systemd.conf and rebooted. (if that's correct, maybe you can add it to the readme?)

Now when I run it I get either this:

# oomd_bin -v
[../Main.cpp:112] oomd running with conf_file=/etc/oomd.json dry=0 verbose=1
[../Config.cpp:119] target_=/sys/fs/cgroup/system.slice
[../../oomd/util/Fs.h:119] Unable to open /etc/oomd_tunables.override
[../shared/Tunables.cpp:32] OOMD_INTERVAL=5
[../shared/Tunables.cpp:32] OOMD_VERBOSE_INTERVAL=300
[../shared/Tunables.cpp:32] OOMD_POST_KILL_DELAY=15
[../shared/Tunables.cpp:32] OOMD_THRESHOLD=60
[../shared/Tunables.cpp:32] OOMD_HIGH_THRESHOLD=80
[../shared/Tunables.cpp:32] OOMD_HIGH_THRESHOLD_DURATION=10
[../shared/Tunables.cpp:32] OOMD_LARGER_THAN=50
[../shared/Tunables.cpp:32] OOMD_GROWTH_ABOVE=80
[../shared/Tunables.cpp:32] OOMD_AVERAGE_SIZE_DECAY=4
[../shared/Tunables.cpp:32] OOMD_FAST_FALL_RATIO=0.85
[../shared/Tunables.cpp:32] OOMD_MIN_SWAP_PCT=15
[../shared/Tunables.cpp:32] OOMD_FBTAX2_WORKLOAD_THRESHOLD=0
Aborted (core dumped)

and for some reason gdb can't figure out the backtrace beyond __GI_abort.

Any idea what I'm doing wrong?

doesn't kill cgroup, unable to set xattr trusted.oomd_ooms=1

Description: oomd has identified a process, but can't kill it.

Package: https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=oomd

Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/util/Fs.cpp:576] Unable to set xattr trusted.oomd_ooms=1 on /sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/gnome-launched-firefox-11870.scope. errno=30
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/plugins/BaseKillPlugin.cpp:96] Trying to kill /sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/gnome-launched-firefox-11870.scope
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/plugins/KillMemoryGrowth-inl.h:168] Picked "user.slice/user-1000.slice/[email protected]/gnome-launched-firefox-11870.scope" (2040MB) based on size > 10% of total 6989MB (size threshold overridden)
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/util/Fs.cpp:576] Unable to set xattr trusted.oomd_kill=0 on /sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/gnome-terminal-server.service. errno=30
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/plugins/BaseKillPlugin.cpp:141] Killed 0: 1377(ssh-agent)[E1] 1401(tmux: server)[E1] 1402(zsh)[E1] 1427(zsh)[E1] 1454(vim)[E1] 1455(zsh)[E1] 1485(htop)[E1] 1496(zsh)[E1] 1521(zsh)[E1] 46339(zsh)[E1] 4>
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/util/Fs.cpp:576] Unable to set xattr trusted.oomd_ooms=1 on /sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/gnome-terminal-server.service. errno=30
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/plugins/BaseKillPlugin.cpp:96] Trying to kill /sys/fs/cgroup/user.slice/user-1000.slice/[email protected]/gnome-terminal-server.service
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/plugins/KillMemoryGrowth-inl.h:168] Picked "user.slice/user-1000.slice/[email protected]/gnome-terminal-server.service" (2370MB) based on size > 10% of total 6989MB (size threshold overridden)
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/OomdContext.cpp:163]   io_cost_cumulative=0 io_cost_rate=0
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/OomdContext.cpp:156]   mem=8MB mem_avg=7MB mem_low=0MB mem_min=0MB mem_prot=0MB anon=6MB swap_usage=0MB
Mar 06 17:53:21 MACHINE_NAME oomd[69346]: [../src/oomd/OomdContext.cpp:151]   pressure=0:0:0-0:0:0

Unable to build oomd

Trying to build and test oomd on Ubuntu-16.04 but facing an error as "This file requires compiler and library support for the ISO C++ 2011 standard".

Where should I enable the -std=c++11 or -std=gnu++11 compiler options?

After meson build && ninja -C build it fails as

The Meson build system
Version: 0.47.2
Source dir: /home/smita/Documents/oomd
Build dir: /home/smita/Documents/oomd/build
Build type: native build
Project name: oomd
Project version: 0.1.0
Native C++ compiler: c++ (gcc 5.4.0 "c++ (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Found pkg-config: /usr/bin/pkg-config (0.29.1)
Native dependency jsoncpp found: YES 1.7.2
Dependency threads found: YES
Dependency GTest found: YES (prebuilt)
Dependency GMock found: YES (prebuilt)
Build targets in project: 10
Found ninja-1.5.1 at /usr/bin/ninja
ninja: Entering directory `build'
[6/31] Compiling C++ object 'oomd@sha/Oomd.cpp.o'.
FAILED: c++ -Ioomd@sha -I. -I.. -I../include -I../shared -I../util -I../ -I../.. -I/usr/include/jsoncpp -fdiagnostics-color=always -pipe -D_FILE_OFFSET_BITS=64 -Wall -Winvalid-pch -Wnon-virtual-dtor -O0 -g -fPIC -pthread -MD -MQ 'oomd@sha/Oomd.cpp.o' -MF 'oomd@sha/Oomd.cpp.o.d' -o 'oomd@sha/Oomd.cpp.o' -c ../Oomd.cpp
In file included from /usr/include/c++/5/atomic:38:0,
from ../../oomd/Oomd.h:20,
from ../Oomd.cpp:18:
/usr/include/c++/5/bits/c++0x_warning.h:32:2: error: #error This file requires compiler and library support for the ISO C++ 2011 standard. This support must be enabled with the -std=c++11 or -std=gnu++11 compiler options.
#error This file requires compiler and library support \

how to use in ubuntu 19.04?

my system is ubuntu 19.04.
without cgroup-fs specified, it reported error:

$ sudo /usr/local/bin/oomd_bin --config /etc/oomd.json   
cgroup path not valid

with cgroup-fs specified with /sys/fs/cgroup/unified, it generated warnings.
I did not know whether it is ok, and how I can check it.

$ sudo /usr/local/bin/oomd_bin --config /etc/oomd.json --cgroup-fs /sys/fs/cgroup/unified/

[../Oomd.cpp:502] Running oomd
[../Oomd.cpp:182] WARNING: cgroup memory controller not enabled on /sys/fs/cgroup/unified/user.slice/user-1000.slice/[email protected]
[../Oomd.cpp:182] WARNING: cgroup memory controller not enabled on /sys/fs/cgroup/unified/system.slice/snapd.service
[../Oomd.cpp:182] WARNING: cgroup memory controller not enabled on /sys/fs/cgroup/unified/system.slice/rpcbind.service

Handle case where cgroups disappear in `Oomd::updateContext()`

Between the time we verify a cgroup exists and has all the right controllers enabled and the time we examine the actual controller files, the cgroup can go away. In other words, between loading all the existing cgroups here and actually inspecting the state here, the latter files can disappear. This usually happens for short lived processes. We currently eat a segfault when we hit this race.

I think we can have all the Fs::read*Pressure calls throw an exception if the file is missing. updateContext can catch any exceptions and abort updating the current cgroup.

Error when trying to build the project

Hey folks, I'm currently trying to build the project from the source but the following error is happening:

❯ meson build && ninja -C build
The Meson build system
Version: 0.49.2
Source dir: /home/diego/workspace/oomd
Build dir: /home/diego/workspace/oomd/build
Build type: native build
Project name: oomd
Project version: 0.2.0
Native C++ compiler: c++ (gcc 7.4.0 "c++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0")
Build machine cpu family: x86_64
Build machine cpu: x86_64
Found Pkg-config: NO
Found CMake: NO
Dependency jsoncpp found: NO 

meson.build:60:0: ERROR:  Pkg-config not found.

A full log can be found at /home/diego/workspace/oomd/build/meson-logs/meson-log.txt
~/workspace/oomd on master ❯                                            at 20:04:02

I have meson, vcpkg and jsoncpp installed here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.