Skip to content

Provide memory usage statistics for each commit #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions metadata-server/metadata-server.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ executable metadata-server
-Wincomplete-uni-patterns
-Wno-unsafe
-threaded
-rtsopts

other-modules: Paths_metadata_server
Config
1 change: 1 addition & 0 deletions metadata-store-postgres/metadata-store-postgres.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ library
-Wredundant-constraints
-Wpartial-fields
-Wcompat
-rtsopts

test-suite integration-tests
hs-source-dirs: test
Expand Down
1 change: 1 addition & 0 deletions nix/haskell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ let
# Enable profiling on executables if the profiling argument is set.
(lib.optionalAttrs profiling {
enableLibraryProfiling = true;
packages.metadata-store-postgres.components.library.enableLibraryProfiling = true;
packages.metadata-server.components.exes.metadata-server.enableExecutableProfiling = true;
packages.metadata-webhook.components.exes.metadata-webhook.enableExecutableProfiling = true;
packages.metadata-validator-github.components.exes.metadata-validator-github.enableExecutableProfiling = true;
Expand Down
12 changes: 10 additions & 2 deletions nix/nixos/metadata-server.nix
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ in {
default = 8080;
description = "the port the metadata server runs on";
};
extraFlags = lib.mkOption {
type = with lib.types; listOf str;
default = [];
description = ''
Extra flags to pass to the metadata-server executable.
'';
example = ["+RTS" "-M500M" "-RTS"];
};
postgres = {
socketdir = lib.mkOption {
type = lib.types.str;
Expand Down Expand Up @@ -75,15 +83,15 @@ in {
config = lib.mkIf cfg.enable {
services.metadata-server.script = let
exec = "metadata-server";
cmd = builtins.filter (x: x != "") [
cmd = builtins.filter (x: x != "") ([
"${cfg.package}/bin/${exec}"
"--db ${config.services.metadata-server.postgres.database}"
"--db-user ${config.services.metadata-server.postgres.user}"
"--db-host ${config.services.metadata-server.postgres.socketdir}"
"--db-table ${config.services.metadata-server.postgres.table}"
"--db-conns ${toString config.services.metadata-server.postgres.numConnections}"
"--port ${toString config.services.metadata-server.port}"
];
] ++ cfg.extraFlags);
in pkgs.writeShellScript "metadata-server" ''
set -euo pipefail
echo "Starting ${exec}: ${lib.concatStringsSep "\"\n echo \"" cmd}"
Expand Down
1 change: 1 addition & 0 deletions nix/nixos/tests/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ with pkgs.commonLib;
callTest = fn: args: forAllSystems (system: let test = importTest fn args system; in hydraJob test // { inherit test; });
in rec {
metadataStorePostgres = callTest ./metadata-store-postgres.nix { inherit haskellPackages; };
memUsage = callTest ./mem-usage.nix {};
# Test will require local faucet setup
# asset = callTest ./docs/asset.nix { inherit (pkgs.commonLib) sources; };
noNixSetup = callTest ./docs/no-nix-setup.nix { inherit haskellPackages; };
Expand Down
142 changes: 142 additions & 0 deletions nix/nixos/tests/mem-usage.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
{ pkgs, ... }:
with pkgs;
let
# Single source of truth for all tutorial constants
database = "postgres";
schema = "api";
table = "metadata";
user = "metadata-server";
postgresUser = "metadata_server";
password = "mysecretpassword";
webRole = "web_anon";
postgresPort = 5432;
metadataServerPort = 8080;
metadataWorkingDir = "/run/metadata-server";

totalMem = 1024;
allowedMem = 100;

vegetaCommands = pkgs.callPackage ./mem-usage/vegeta-attack.nix { port = metadataServerPort; };
vegetaGo = pkgs.writeShellScriptBin "vegeta-go" ''
cat ${vegetaCommands} | vegeta attack -duration 10s -connections 1 -rate 100/s -output vegeta.log
'';
in
{
name = "metadata-server-mem-usage-test";

nodes = {
server = { config, ... }: {
nixpkgs.pkgs = pkgs;
imports = [
../.
];

virtualisation.memorySize = totalMem;

environment.systemPackages = [ pkgs.vegeta pkgs.htop vegetaGo pkgs.haskellPackages.hp2pretty pkgs.haskellPackages.profiteur ];

services.postgresql = {
enable = true;
port = postgresPort;
package = pkgs.postgresql;
ensureDatabases = [ "${database}" ];
ensureUsers = [
{
name = "${postgresUser}";
ensurePermissions = {
"DATABASE ${database}" = "ALL PRIVILEGES";
};
}
];
identMap = ''
metadata-server-users root ${postgresUser}
metadata-server-users ${user} ${postgresUser}
metadata-server-users postgres postgres
'';
authentication = ''
local all all ident map=metadata-server-users
'';

settings =
{
log_connections = true;
# log_statement = "all";
logging_collector = true;
log_disconnections = true;
log_destination = lib.mkForce "syslog";
};
};

users = {
mutableUsers = false;

users = {
# For ease of debugging the VM as the `root` user
root.password = "";

# Create a system user that matches the database user so that we
# can use peer authentication.
"${user}".isSystemUser = true;
};
};

services.metadata-server = {
enable = true;

user = user;
port = metadataServerPort;

postgres = {
port = postgresPort;
table = table;
user = postgresUser;
database = database;
};

extraFlags = ["+RTS" "-h" "-p" "-RTS"];

metadataServerPkgs = (import ../../../. {}).profiledProject;
};
systemd.services.metadata-server.serviceConfig.WorkingDirectory = metadataWorkingDir;
systemd.services.metadata-server.serviceConfig.RuntimeDirectoryPreserve = true;
systemd.services.metadata-server.serviceConfig.KillSignal = "SIGINT";
systemd.services.metadata-server.serviceConfig.TimeoutStopSec = "10";

systemd.tmpfiles.rules = [
"L /root/vegeta.atk - - - - ${vegetaCommands}"
];
};
};

testScript =
''
# fmt: off
import os
import pathlib

start_all()

server.wait_for_open_port(${toString postgresPort})
server.wait_for_open_port(${toString metadataServerPort})
server.succeed("cat ${vegetaCommands} | vegeta attack -duration 10s -connections 1 -rate 10/s")
# Stop metadata-server.service so GHC writes out .prof file contents
server.succeed("systemctl stop metadata-server.service")
server.succeed("sleep 10")
server.succeed("cd ${metadataWorkingDir} && hp2pretty metadata-server.hp")
server.succeed("cd ${metadataWorkingDir} && profiteur metadata-server.prof")
server.copy_from_vm("${metadataWorkingDir}/metadata-server.svg")
server.copy_from_vm("${metadataWorkingDir}/metadata-server.prof")
server.copy_from_vm("${metadataWorkingDir}/metadata-server.prof.html")

def write_hydra_build_products(data):
out_dir = pathlib.Path(os.environ.get("out", os.getcwd()))
hydra_build_products = out_dir / "nix-support" / "hydra-build-products"
hydra_build_products.parent.mkdir(exist_ok=True, parents=True)
with hydra_build_products.open(mode="a") as f:
f.write(data.format(out_dir) + "\n")

write_hydra_build_products("file svg {}/metadata-server.svg")
write_hydra_build_products("file html {}/metadata-server.prof.html")
write_hydra_build_products("file text {}/metadata-server.prof")
'';
}
Loading