diff --git a/lib.cpp b/lib.cpp
index b43e63d86b70fc95dcd737584578564027984de6..b8475822ce2add60ca65162c034ea0619830e846 100644
--- a/lib.cpp
+++ b/lib.cpp
@@ -7,6 +7,7 @@
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdarg.h>
+#include <sys/resource.h>
 
 namespace lib
 {
@@ -75,6 +76,8 @@ namespace lib
 	namespace internal
 	{
 #define verdict_add(a...) do{ int r = sprintf(verdict+verdict_len, a); assert(r>0); verdict_len += r;}while(false)
+		std::vector<std::pair<std::string, std::string>> user_data;
+
 		void add_to_log_file(char * verdict)
 		{
 			char * logfile = getenv("LOGFILE");
@@ -92,12 +95,27 @@ namespace lib
 			// TODO better escapeing
 			verdict_add("]");
 		}
-		void validate_and_format_verdict(int n, vector<int> input, vector<bool> out, char * verdict, int & verdict_len, const char * algo)
+		void validate_and_format_verdict(int n, vector<int> input, vector<bool> out, char * verdict, int & verdict_len, const char * algo, int wallclock_s)
 		{
 			verdict_add(", \"algo\":\"%s\", \"version\": %d, \"n\": %d, \"score\":%d",
 					               algo,         VERSION,         n, calc_score(n, out)
 					);
 
+			verdict_add(", \"data\": {\"_\":0");
+			for(auto it : user_data)
+			{
+				verdict_add(", \"%s\": %s", it.first.c_str(), it.second.c_str());
+			}
+			verdict_add("}");
+			{
+				verdict_add(", \"resources\": {");
+				struct rusage rus;
+				getrusage(RUSAGE_SELF, &rus);
+				verdict_add("\"memory_kb\":%d", rus.ru_maxrss);
+				verdict_add(",\"cpu_time_s\":%d", rus.ru_utime.tv_sec);
+				verdict_add(",\"wallclock_s\":%d", wallclock_s);
+				verdict_add("}");
+			}
 			if(ALLOW_MISTAKES)
 			{
 				verdict_add(", \"mistakes\": %d", calc_mistakes(n, input, out));
@@ -155,4 +173,13 @@ namespace lib
 			assert(fread(input.data(), sizeof(int), 2*n, stdin) == 2*n);
 		}
 	}
+	void log_data(const char * key, const char *fmt, ...)
+	{
+		int buffer_len = 1000;
+		char buffer[buffer_len+1];
+		va_list args;
+		va_start(args, fmt);
+		vsnprintf(buffer, buffer_len, fmt, args);
+		internal::user_data.push_back(std::make_pair(std::string(key), std::string(buffer)));
+	}
 }
diff --git a/lib.h b/lib.h
index ed6ed9ce5f84777e60dddd376e72f1902f3d4fb4..89f46f9ca1077273d96dd0870d432e3cd26dd0b5 100644
--- a/lib.h
+++ b/lib.h
@@ -28,11 +28,13 @@ namespace lib
 	
 	std::pair<FILE *, FILE*> dualpopen(const char * cmd);
 
+	void log_data(const char * key, const char *fmt, ...);
+
 	namespace internal
 	{
 		void format_args(char * verdict, int & verdict_len, int argc, char const* const* argv);
 		void add_to_log_file(char * verdict);
-		void validate_and_format_verdict(int n, vector<int> input, vector<bool> out, char * verdict, int & verdict_len, const char * algo);
+		void validate_and_format_verdict(int n, vector<int> input, vector<bool> out, char * verdict, int & verdict_len, const char * algo, int wallclock_s);
 		void print_data(int n, vector<int> input, vector<bool> out, const char * verdict);
 		void load_data(int &n, vector<int> &input, vector<bool> &out, char *& verdict, bool & mistakes);
 
diff --git a/main.cpp b/main.cpp
index 23ada50879070572249fd80fba710572e48f88b4..789484592037c59875ad86abb3d8f5080df8daa7 100644
--- a/main.cpp
+++ b/main.cpp
@@ -3,6 +3,7 @@
 #include <algorithm>
 #include <cassert>
 #include <cstring>
+#include <unistd.h>
 
 #define verdict_add(a...) do{ int r = sprintf(verdict+verdict_len, a); assert(r>0); verdict_len += r;}while(false)
 
@@ -27,13 +28,21 @@ int main(int argc, char ** argv)
 	fo(i,n) in[n+i] = i;
 	random_shuffle(in.begin(), in.end());
 
+	fflush(stdout);
+	int old_stdout = dup(1);
+	dup2(2, 1);
+	long long time_before = time(0);
 	auto out = solve(n, in, argc-3, argv+3);
+	long long time_after = time(0);
+	fflush(stdout);
+	dup2(old_stdout, 1);
+
 	char verdict[1000];
 	int verdict_len=0;
 
 	verdict_add("{\"_\":0");
 	format_args(verdict, verdict_len, argc-3, argv+3);
-	validate_and_format_verdict(n, in, out, verdict, verdict_len, argv[0]);
+	validate_and_format_verdict(n, in, out, verdict, verdict_len, argv[0], time_after-time_before);
 	verdict_add(", \"seed\": %d", seed);
 	verdict_add("},\n");
 
diff --git a/pipe.cpp b/pipe.cpp
index 93ad73651e834bb0c62fce98b3545e01cd447ff2..326ab336c037036920f6efd8eb47dba5e88f0aa7 100644
--- a/pipe.cpp
+++ b/pipe.cpp
@@ -24,13 +24,15 @@ int main(int argc, char ** argv)
 	load_data(n, in, out, prev_verdict, mistakes);
 	assert(ALLOW_INPUT_MISTAKES || !mistakes);
 
+	long long time_before = time(0);
 	out = solve(n, in, out, argc-1, argv+1);
+	long long time_after = time(0);
 	char verdict[1000];
 	int verdict_len=0;
 
 	verdict_add("{\"_\":0");
 	format_args(verdict, verdict_len, argc-1, argv+1);
-	validate_and_format_verdict(n, in, out, verdict, verdict_len, argv[0]);
+	validate_and_format_verdict(n, in, out, verdict, verdict_len, argv[0], time_after-time_before);
 	verdict_add(", \"from\": %s", prev_verdict);
 	verdict_add("},\n");