diff --git a/common/build/Utilities/utilities.vcxproj b/common/build/Utilities/utilities.vcxproj
index 1ee3d0194f..c52ff622bd 100644
--- a/common/build/Utilities/utilities.vcxproj
+++ b/common/build/Utilities/utilities.vcxproj
@@ -117,6 +117,7 @@
+
Create
Create
diff --git a/common/build/Utilities/utilities.vcxproj.filters b/common/build/Utilities/utilities.vcxproj.filters
index 35d467a66d..e28bf1b2fb 100644
--- a/common/build/Utilities/utilities.vcxproj.filters
+++ b/common/build/Utilities/utilities.vcxproj.filters
@@ -41,6 +41,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/common/include/Utilities/Perf.h b/common/include/Utilities/Perf.h
new file mode 100644
index 0000000000..f24e897df2
--- /dev/null
+++ b/common/include/Utilities/Perf.h
@@ -0,0 +1,57 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2015 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#pragma once
+
+namespace Perf {
+
+ struct Info
+ {
+ uptr m_x86;
+ u32 m_size;
+ char m_symbol[20];
+ // The idea is to keep static zones that are set only
+ // once.
+ bool m_dynamic;
+
+ Info(uptr x86, u32 size, const char* symbol);
+ Info(uptr x86, u32 size, const char* symbol, u32 pc);
+ void Print(FILE* fp);
+ };
+
+ class InfoVector
+ {
+ std::vector m_v;
+ char m_prefix[20];
+
+ public:
+
+ InfoVector(const char* prefix);
+
+ void print(FILE* fp);
+ void map(uptr x86, u32 size, const char* symbol);
+ void map(uptr x86, u32 size, u32 pc);
+ void reset();
+
+ };
+
+ void dump();
+ void dump_and_reset();
+
+ extern InfoVector any;
+ extern InfoVector ee;
+ extern InfoVector iop;
+ extern InfoVector vu;
+}
diff --git a/common/src/Utilities/CMakeLists.txt b/common/src/Utilities/CMakeLists.txt
index dea7c7dcc8..0e125e20c1 100644
--- a/common/src/Utilities/CMakeLists.txt
+++ b/common/src/Utilities/CMakeLists.txt
@@ -61,6 +61,7 @@ set(UtilitiesSources
Mutex.cpp
PathUtils.cpp
PrecompiledHeader.cpp
+ Perf.cpp
pxCheckBox.cpp
pxRadioPanel.cpp
pxStaticText.cpp
diff --git a/common/src/Utilities/Perf.cpp b/common/src/Utilities/Perf.cpp
new file mode 100644
index 0000000000..ce6c284ca6
--- /dev/null
+++ b/common/src/Utilities/Perf.cpp
@@ -0,0 +1,140 @@
+/* PCSX2 - PS2 Emulator for PCs
+ * Copyright (C) 2002-2015 PCSX2 Dev Team
+ *
+ * PCSX2 is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU Lesser General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with PCSX2.
+ * If not, see .
+ */
+
+#include "PrecompiledHeader.h"
+
+#include "Perf.h"
+
+//#define ProfileWithPerf
+#define MERGE_BLOCK_RESULT
+
+
+namespace Perf
+{
+ // Warning object aren't thread safe
+ InfoVector any("");
+ InfoVector ee("EE");
+ InfoVector iop("IOP");
+ InfoVector vu("VU");
+
+// Perf is only supported on linux
+#if defined(__linux__) && defined(ProfileWithPerf)
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Implementation of the Info object
+ ////////////////////////////////////////////////////////////////////////////////
+
+ Info::Info(uptr x86, u32 size, const char* symbol) : m_x86(x86), m_size(size), m_dynamic(false)
+ {
+ strncpy(m_symbol, symbol, sizeof(m_symbol));
+ }
+
+ Info::Info(uptr x86, u32 size, const char* symbol, u32 pc) : m_x86(x86), m_size(size), m_dynamic(true)
+ {
+ snprintf(m_symbol, sizeof(m_symbol), "%s_0x%08x", symbol, pc);
+ }
+
+ void Info::Print(FILE* fp)
+ {
+ fprintf(fp, "%x %x %s\n", m_x86, m_size, m_symbol);
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Implementation of the InfoVector object
+ ////////////////////////////////////////////////////////////////////////////////
+
+ InfoVector::InfoVector(const char* prefix)
+ {
+ strncpy(m_prefix, prefix, sizeof(m_prefix));
+ }
+
+ void InfoVector::print(FILE* fp)
+ {
+ for(auto&& it : m_v) it.Print(fp);
+ }
+
+ void InfoVector::map(uptr x86, u32 size, const char* symbol)
+ {
+ // This function is typically used for dispatcher and recompiler.
+ // Dispatchers are on a page and must always be kept.
+ // Recompilers are much bigger (TODO check VIF) and are only
+ // useful when MERGE_BLOCK_RESULT is defined
+
+#ifdef MERGE_BLOCK_RESULT
+ m_v.emplace_back(x86, size, symbol);
+#else
+ if (size < 8 * _1kb) m_v.emplace_back(x86, size, symbol);
+#endif
+ }
+
+ void InfoVector::map(uptr x86, u32 size, u32 pc)
+ {
+#ifndef MERGE_BLOCK_RESULT
+ m_v.emplace_back(x86, size, m_prefix, pc);
+#endif
+ }
+
+ void InfoVector::reset()
+ {
+ auto dynamic = std::remove_if(m_v.begin(), m_v.end(), [](Info i) { return i.m_dynamic; });
+ m_v.erase(dynamic, m_v.end());
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Global function
+ ////////////////////////////////////////////////////////////////////////////////
+
+ void dump()
+ {
+ char file[256];
+ snprintf(file, 250, "/tmp/perf-%d.map", getpid());
+ FILE* fp = fopen(file, "w");
+
+ any.print(fp);
+ ee.print(fp);
+ iop.print(fp);
+ vu.print(fp);
+
+ if (fp)
+ fclose(fp);
+ }
+
+ void dump_and_reset()
+ {
+ dump();
+
+ any.reset();
+ ee.reset();
+ iop.reset();
+ vu.reset();
+ }
+
+#else
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Dummy implementation
+ ////////////////////////////////////////////////////////////////////////////////
+
+ InfoVector::InfoVector(const char* prefix) {}
+ void InfoVector::map(uptr x86, u32 size, const char* symbol) {}
+ void InfoVector::map(uptr x86, u32 size, u32 pc) {}
+ void InfoVector::reset() {}
+
+ void dump() {}
+ void dump_and_reset() {}
+
+#endif
+
+}