From f8a04d21d1bfccb3fce8bec4142ef8062c506340 Mon Sep 17 00:00:00 2001 From: jaxne Date: Mon, 8 Jun 2020 02:32:28 -0600 Subject: [PATCH 1/5] aetime: Inital commit Implemented a basic compilation timer --- aetime.c | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++ aetime.exe | Bin 0 -> 136704 bytes build.bat | 5 ++ 3 files changed, 194 insertions(+) create mode 100644 aetime.c create mode 100644 aetime.exe create mode 100644 build.bat diff --git a/aetime.c b/aetime.c new file mode 100644 index 00000000..794648e0 --- /dev/null +++ b/aetime.c @@ -0,0 +1,189 @@ +#include + +#define global static +#define uint unsigned int +#define u8 uint8_t +#define u32 uint32_t +#define f32 float + +#define GenerateMagic(a, b, c, d) (((u32)(a) << 0) | ((u32)(b) << 8) | ((u32)(c) << 16) | ((u32)(d) << 24)) + +#pragma pack(push, 1) +#define AET_MAGIC_VALUE GenerateMagic('a', 'e', 't', 'c') +typedef struct timer_file_header { + u32 Magic; +} timer_file_header; + +typedef struct timer_file_entry { + f32 Elapsed; +} timer_file_entry; + +typedef struct timer_entry_array { + u32 EntryCount; + timer_file_entry* Entries; +} timer_entry_array; +#pragma pack(pop) + +// note(jax): Eventually support Mac/Linux... +#include +#include +#include + +int StringLength(char* String) { + int Count = 0; + while (*String++) { + ++Count; + } + return Count; +} + +bool StringsMatch(char* A, char* B) { + if (!A || !B) { + return false; + } + + while (*A && *B) { + if (*A != *B){ + return false; + } + + ++A; + ++B; + } + + if (*A != *B){ + return false; + } else { + return true; + } +} + +global f32 GlobalFrequency; + +#define COUNTERTOMS 1.f / (GlobalFrequency / 1000.f) +#define COUNTERTOUS COUNTERTOMS * 1000.f +#define COUNTERTONS COUNTERTOUS * 1000.f +#define COUNTERTOS COUNTERTOMS / 1000.f + +global void Usage(char** Args) { + fprintf(stderr, "Usage: %s --begin .aet [-v|--v|--verbose|-verbose]\n", Args[0]); + fprintf(stderr, " %s --end .aet [-v|--v|--verbose|-verbose]\n", Args[0]); +} + +// This function assumes FileName is a full path with an extension +char* GetBaseName(char* FileName) { + int BaseNameSize = 0; + char* BaseName = malloc(sizeof(char)*MAX_PATH); + char* BaseNameBegin = FileName; + char* BaseNameEnd = FileName + StringLength(FileName); + bool RightOfPeriod = false; + for (char* Scan = BaseNameBegin; *Scan; ++Scan) { + if ((Scan[0] == '\\') || (Scan[0] == '/')) { + BaseNameBegin = Scan + 1; + } + + if (Scan[0] == '.') { + BaseNameEnd = Scan; + RightOfPeriod = true; + } + else if (!RightOfPeriod) { + ++BaseNameSize; + } + } + + memcpy(BaseName, BaseNameBegin, BaseNameSize); + BaseName[BaseNameSize] = 0; + + return BaseName; +} + +int main(int ArgCount, char** Args) { + bool IsVerbose = false; + if (StringsMatch(Args[3], "--verbose") || + StringsMatch(Args[3], "--v") || + StringsMatch(Args[3], "-verbose") || + StringsMatch(Args[3], "-v")) { + IsVerbose = true; + } + + LARGE_INTEGER _F; + QueryPerformanceFrequency(&_F); + GlobalFrequency = (f32)_F.QuadPart; + + char Path[MAX_PATH]; + GetTempPathA(MAX_PATH, Path); + + if (ArgCount >= 3) { + if (StringsMatch(Args[1], "--begin")) { + char* FileName = Args[2]; + sprintf(Path, "%s\\%s", Path, FileName); + FILE* Dest = fopen(Path, "wb"); + if (Dest) { + if (IsVerbose) { + printf("Writing to '%s'\n", Path); + } + + timer_file_header Header = {0}; + Header.Magic = AET_MAGIC_VALUE; + fwrite(&Header, sizeof(Header), 1, Dest); + + LARGE_INTEGER Start; + timer_file_entry Entry = {0}; + QueryPerformanceCounter(&Start); + Entry.Elapsed = (f32)Start.QuadPart; + + printf("Compilation started for %s\n", GetBaseName(FileName)); + if (fwrite(&Entry, sizeof(Entry), 1, Dest) != 1) { + fprintf(stderr, "ERROR: Failed to append new start entry to file '%s'.\n", FileName); + } else { + fclose(Dest); + } + } else { + fprintf(stderr, "ERROR: Failed to open file '%s'.\n", FileName); + } + } else if (StringsMatch(Args[1], "--end")) { + char* FileName = Args[2]; + sprintf(Path, "%s\\%s", Path, FileName); + + FILE* Dest = fopen(Path, "rb"); + if (Dest) { + if (IsVerbose) { + printf("Reading from '%s'\n", Path); + } + + timer_file_header Header = {0}; + fread(&Header, sizeof(Header), 1, Dest); + if (IsVerbose) { + printf("struct timer_file_header {\n Magic: %u\n};\n", Header.Magic); + } + + timer_file_entry Entry = {0}; + if(fread(&Entry, sizeof(Entry), 1, Dest) == 1) { + LARGE_INTEGER End; + QueryPerformanceCounter(&End); + + f32 Elapsed = ((f32)End.QuadPart) - Entry.Elapsed; + f32 Seconds = Elapsed * COUNTERTOS; + f32 Milliseconds = Elapsed * COUNTERTOMS; + printf("Compilation ended: %f seconds\n", Seconds); + } else { + fprintf(stderr, "ERROR: Failed to read start entry from file '%s'.\n", FileName); + } + + fclose(Dest); + + if (remove(Path) != 0) { + fprintf(stderr, "ERROR: Failed to remove file '%s'.\n", FileName); + } + } else { + fprintf(stderr, "ERROR: Failed to open file '%s'.\n", FileName); + } + } else { + Usage(Args); + } + } else { + Usage(Args); + } + + return 1; +} \ No newline at end of file diff --git a/aetime.exe b/aetime.exe new file mode 100644 index 0000000000000000000000000000000000000000..9f922adf152ff0a74a90f2544752b6a083f7dc98 GIT binary patch literal 136704 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 nul \ No newline at end of file From 2adc7fe05cc448e8edafc4e45063622d7c15e45a Mon Sep 17 00:00:00 2001 From: jaxne Date: Tue, 9 Jun 2020 00:52:00 -0600 Subject: [PATCH 2/5] Add some more tools --- aetime.c | 189 ----------------------------------------------------- aetime.exe | Bin 136704 -> 136704 bytes 2 files changed, 189 deletions(-) delete mode 100644 aetime.c diff --git a/aetime.c b/aetime.c deleted file mode 100644 index 794648e0..00000000 --- a/aetime.c +++ /dev/null @@ -1,189 +0,0 @@ -#include - -#define global static -#define uint unsigned int -#define u8 uint8_t -#define u32 uint32_t -#define f32 float - -#define GenerateMagic(a, b, c, d) (((u32)(a) << 0) | ((u32)(b) << 8) | ((u32)(c) << 16) | ((u32)(d) << 24)) - -#pragma pack(push, 1) -#define AET_MAGIC_VALUE GenerateMagic('a', 'e', 't', 'c') -typedef struct timer_file_header { - u32 Magic; -} timer_file_header; - -typedef struct timer_file_entry { - f32 Elapsed; -} timer_file_entry; - -typedef struct timer_entry_array { - u32 EntryCount; - timer_file_entry* Entries; -} timer_entry_array; -#pragma pack(pop) - -// note(jax): Eventually support Mac/Linux... -#include -#include -#include - -int StringLength(char* String) { - int Count = 0; - while (*String++) { - ++Count; - } - return Count; -} - -bool StringsMatch(char* A, char* B) { - if (!A || !B) { - return false; - } - - while (*A && *B) { - if (*A != *B){ - return false; - } - - ++A; - ++B; - } - - if (*A != *B){ - return false; - } else { - return true; - } -} - -global f32 GlobalFrequency; - -#define COUNTERTOMS 1.f / (GlobalFrequency / 1000.f) -#define COUNTERTOUS COUNTERTOMS * 1000.f -#define COUNTERTONS COUNTERTOUS * 1000.f -#define COUNTERTOS COUNTERTOMS / 1000.f - -global void Usage(char** Args) { - fprintf(stderr, "Usage: %s --begin .aet [-v|--v|--verbose|-verbose]\n", Args[0]); - fprintf(stderr, " %s --end .aet [-v|--v|--verbose|-verbose]\n", Args[0]); -} - -// This function assumes FileName is a full path with an extension -char* GetBaseName(char* FileName) { - int BaseNameSize = 0; - char* BaseName = malloc(sizeof(char)*MAX_PATH); - char* BaseNameBegin = FileName; - char* BaseNameEnd = FileName + StringLength(FileName); - bool RightOfPeriod = false; - for (char* Scan = BaseNameBegin; *Scan; ++Scan) { - if ((Scan[0] == '\\') || (Scan[0] == '/')) { - BaseNameBegin = Scan + 1; - } - - if (Scan[0] == '.') { - BaseNameEnd = Scan; - RightOfPeriod = true; - } - else if (!RightOfPeriod) { - ++BaseNameSize; - } - } - - memcpy(BaseName, BaseNameBegin, BaseNameSize); - BaseName[BaseNameSize] = 0; - - return BaseName; -} - -int main(int ArgCount, char** Args) { - bool IsVerbose = false; - if (StringsMatch(Args[3], "--verbose") || - StringsMatch(Args[3], "--v") || - StringsMatch(Args[3], "-verbose") || - StringsMatch(Args[3], "-v")) { - IsVerbose = true; - } - - LARGE_INTEGER _F; - QueryPerformanceFrequency(&_F); - GlobalFrequency = (f32)_F.QuadPart; - - char Path[MAX_PATH]; - GetTempPathA(MAX_PATH, Path); - - if (ArgCount >= 3) { - if (StringsMatch(Args[1], "--begin")) { - char* FileName = Args[2]; - sprintf(Path, "%s\\%s", Path, FileName); - FILE* Dest = fopen(Path, "wb"); - if (Dest) { - if (IsVerbose) { - printf("Writing to '%s'\n", Path); - } - - timer_file_header Header = {0}; - Header.Magic = AET_MAGIC_VALUE; - fwrite(&Header, sizeof(Header), 1, Dest); - - LARGE_INTEGER Start; - timer_file_entry Entry = {0}; - QueryPerformanceCounter(&Start); - Entry.Elapsed = (f32)Start.QuadPart; - - printf("Compilation started for %s\n", GetBaseName(FileName)); - if (fwrite(&Entry, sizeof(Entry), 1, Dest) != 1) { - fprintf(stderr, "ERROR: Failed to append new start entry to file '%s'.\n", FileName); - } else { - fclose(Dest); - } - } else { - fprintf(stderr, "ERROR: Failed to open file '%s'.\n", FileName); - } - } else if (StringsMatch(Args[1], "--end")) { - char* FileName = Args[2]; - sprintf(Path, "%s\\%s", Path, FileName); - - FILE* Dest = fopen(Path, "rb"); - if (Dest) { - if (IsVerbose) { - printf("Reading from '%s'\n", Path); - } - - timer_file_header Header = {0}; - fread(&Header, sizeof(Header), 1, Dest); - if (IsVerbose) { - printf("struct timer_file_header {\n Magic: %u\n};\n", Header.Magic); - } - - timer_file_entry Entry = {0}; - if(fread(&Entry, sizeof(Entry), 1, Dest) == 1) { - LARGE_INTEGER End; - QueryPerformanceCounter(&End); - - f32 Elapsed = ((f32)End.QuadPart) - Entry.Elapsed; - f32 Seconds = Elapsed * COUNTERTOS; - f32 Milliseconds = Elapsed * COUNTERTOMS; - printf("Compilation ended: %f seconds\n", Seconds); - } else { - fprintf(stderr, "ERROR: Failed to read start entry from file '%s'.\n", FileName); - } - - fclose(Dest); - - if (remove(Path) != 0) { - fprintf(stderr, "ERROR: Failed to remove file '%s'.\n", FileName); - } - } else { - fprintf(stderr, "ERROR: Failed to open file '%s'.\n", FileName); - } - } else { - Usage(Args); - } - } else { - Usage(Args); - } - - return 1; -} \ No newline at end of file diff --git a/aetime.exe b/aetime.exe index 9f922adf152ff0a74a90f2544752b6a083f7dc98..6532c3e08975ef595335a143debcae4a8afc8c90 100644 GIT binary patch delta 29 jcmZoz!_lyYW5N&SDQoUE{@(hVapyS@bNlx5jGk@)>LCxb delta 29 jcmZoz!_lyYW5N&SBj4^e{@(hVapyS@bNlx5jGk@)_eKz= From 376dddcc058181bc61519529c8cfaed68e52ee6f Mon Sep 17 00:00:00 2001 From: jaxne Date: Tue, 9 Jun 2020 00:52:43 -0600 Subject: [PATCH 3/5] aetime: Add license & instructions --- aetime.c | 412 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 412 insertions(+) create mode 100644 aetime.c diff --git a/aetime.c b/aetime.c new file mode 100644 index 00000000..1f80c730 --- /dev/null +++ b/aetime.c @@ -0,0 +1,412 @@ +/* Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright (c) 2020 by Asteria Development + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* =================================================================== + + $ + + aetime works under the same premise as Casey Muratori's ctime under + the public domain. It's a small utility that allows you to time how + long your machine spends building your project. It works in the same + manner as a begin/end block in your typical profiler. + + $ WARNING + --------- + + This software is provided UNDER AN "AS IS" BASIS. The author makes NO + WARRENTY to the RELIABILITY of this software. Take this message as your + only warning, USE AT YOUR OWN RISK. This shit could even format your + entire disk! Not my fault though. + + INSTRUCTIONS + ------------ + + On the first line of your build script, write + aetime --begin .aet + then on the last line, write + aetime --end .aet + and the program will output how many seconds it took to build your project! + + Also if you must debug the project, you can append a '-v' flag to the end + of the argument list for additional debug output into the console. + + ======================================================================== */ + +#include + +#define global static +#define uint unsigned int +#define u8 uint8_t +#define u32 uint32_t +#define f32 float + +#define GenerateMagic(a, b, c, d) (((u32)(a) << 0) | ((u32)(b) << 8) | ((u32)(c) << 16) | ((u32)(d) << 24)) + +#pragma pack(push, 1) +#define AET_MAGIC_VALUE GenerateMagic('a', 'e', 't', 'c') +typedef struct timer_file_header { + u32 Magic; +} timer_file_header; + +typedef struct timer_file_entry { + f32 Elapsed; +} timer_file_entry; + +typedef struct timer_entry_array { + u32 EntryCount; + timer_file_entry* Entries; +} timer_entry_array; +#pragma pack(pop) + +// note(jax): Eventually support Mac/Linux... +#include +#include +#include + +int StringLength(char* String) { + int Count = 0; + while (*String++) { + ++Count; + } + return Count; +} + +bool StringsMatch(char* A, char* B) { + if (!A || !B) { + return false; + } + + while (*A && *B) { + if (*A != *B){ + return false; + } + + ++A; + ++B; + } + + if (*A != *B){ + return false; + } else { + return true; + } +} + +global f32 GlobalFrequency; + +#define COUNTERTOMS 1.f / (GlobalFrequency / 1000.f) +#define COUNTERTOUS COUNTERTOMS * 1000.f +#define COUNTERTONS COUNTERTOUS * 1000.f +#define COUNTERTOS COUNTERTOMS / 1000.f + +global void Usage(char** Args) { + fprintf(stderr, "Usage: %s --begin .aet [-v|--v|--verbose|-verbose]\n", Args[0]); + fprintf(stderr, " %s --end .aet [-v|--v|--verbose|-verbose]\n", Args[0]); +} + +// This function assumes FileName is a full path with an extension +char* GetBaseName(char* FileName) { + int BaseNameSize = 0; + char* BaseName = malloc(sizeof(char)*MAX_PATH); + char* BaseNameBegin = FileName; + char* BaseNameEnd = FileName + StringLength(FileName); + bool RightOfPeriod = false; + for (char* Scan = BaseNameBegin; *Scan; ++Scan) { + if ((Scan[0] == '\\') || (Scan[0] == '/')) { + BaseNameBegin = Scan + 1; + } + + if (Scan[0] == '.') { + BaseNameEnd = Scan; + RightOfPeriod = true; + } + else if (!RightOfPeriod) { + ++BaseNameSize; + } + } + + memcpy(BaseName, BaseNameBegin, BaseNameSize); + BaseName[BaseNameSize] = 0; + + return BaseName; +} + +int main(int ArgCount, char** Args) { + bool IsVerbose = false; + if (StringsMatch(Args[3], "--verbose") || + StringsMatch(Args[3], "--v") || + StringsMatch(Args[3], "-verbose") || + StringsMatch(Args[3], "-v")) { + IsVerbose = true; + } + + LARGE_INTEGER _F; + QueryPerformanceFrequency(&_F); + GlobalFrequency = (f32)_F.QuadPart; + + char Path[MAX_PATH]; + GetTempPathA(MAX_PATH, Path); + + if (ArgCount >= 3) { + if (StringsMatch(Args[1], "--begin")) { + char* FileName = Args[2]; + sprintf(Path, "%s\\%s", Path, FileName); + FILE* Dest = fopen(Path, "wb"); + if (Dest) { + if (IsVerbose) { + printf("Writing to '%s'\n", Path); + } + + timer_file_header Header = {0}; + Header.Magic = AET_MAGIC_VALUE; + fwrite(&Header, sizeof(Header), 1, Dest); + + LARGE_INTEGER Start; + timer_file_entry Entry = {0}; + QueryPerformanceCounter(&Start); + Entry.Elapsed = (f32)Start.QuadPart; + + printf("Compilation started for %s\n", GetBaseName(FileName)); + if (fwrite(&Entry, sizeof(Entry), 1, Dest) != 1) { + fprintf(stderr, "ERROR: Failed to append new start entry to file '%s'.\n", FileName); + } else { + fclose(Dest); + } + } else { + fprintf(stderr, "ERROR: Failed to open file '%s'.\n", FileName); + } + } else if (StringsMatch(Args[1], "--end")) { + char* FileName = Args[2]; + sprintf(Path, "%s\\%s", Path, FileName); + + FILE* Dest = fopen(Path, "rb"); + if (Dest) { + if (IsVerbose) { + printf("Reading from '%s'\n", Path); + } + + timer_file_header Header = {0}; + fread(&Header, sizeof(Header), 1, Dest); + if (IsVerbose) { + printf("struct timer_file_header {\n Magic: %u\n};\n", Header.Magic); + } + + timer_file_entry Entry = {0}; + if(fread(&Entry, sizeof(Entry), 1, Dest) == 1) { + LARGE_INTEGER End; + QueryPerformanceCounter(&End); + + f32 Elapsed = ((f32)End.QuadPart) - Entry.Elapsed; + f32 Seconds = Elapsed * COUNTERTOS; + f32 Milliseconds = Elapsed * COUNTERTOMS; + printf("Compilation ended: %f seconds\n", Seconds); + } else { + fprintf(stderr, "ERROR: Failed to read start entry from file '%s'.\n", FileName); + } + + fclose(Dest); + + if (remove(Path) != 0) { + fprintf(stderr, "ERROR: Failed to remove file '%s'.\n", FileName); + } + } else { + fprintf(stderr, "ERROR: Failed to open file '%s'.\n", FileName); + } + } else { + Usage(Args); + } + } else { + Usage(Args); + } + + return 1; +} \ No newline at end of file From 5a0fc7a7e36dd6198fdb2671bef694bb48dc628e Mon Sep 17 00:00:00 2001 From: jaxne Date: Mon, 29 Jun 2020 20:21:11 -0600 Subject: [PATCH 4/5] aetime: Port to linux --- aetime | Bin 0 -> 17384 bytes aetime.c | 179 +++++++++++++++++++++++++++++++++++++++++++++++++++--- build.bat | 2 +- build.sh | 5 ++ 4 files changed, 178 insertions(+), 8 deletions(-) create mode 100755 aetime create mode 100755 build.sh diff --git a/aetime b/aetime new file mode 100755 index 0000000000000000000000000000000000000000..09260228c9b59c979d86e2de83bd6e49bca80de5 GIT binary patch literal 17384 zcmeHPeQ;aVmA|r_#0iOHLLhDk&D-FBLu}CV>*| z@7#Bf^dwshv;TBwR@d|1x#xG!IrrT2?z`_^y?6akOZ)l?heL33ikpSxF18S#DmZWx zO90?#k51oGv(O-74*o@FPb>) zn^k?K;<8=&&y?a%X+>|ObM?vJ~1ra=wK8yTF$gNLtLJCFFll0{>MB{OJ<-gC+1CCGclU z;7^pm&y>J_RsvrFT*FbE#sEwg=h?Vu)8W*gG#tfg4FIheBp&@cVTMCr`3m*v)gln+ z?u$hO2{RZs0|60e>(~$o8*!sMk}!>U$A)#iv8d4z?CdqHvS~|Tv(GYzTz4oGND$|x zxsgu0d9TlB^XRpnRTRjI+@BL8Lj~^eJYtoS zlmlgbpgb-uh(vIU&k&d6dJ^_G-+B^5L8Vxx_{Syh6b*_`E{fn*t`KX$Q{wTR@8`4X z<~yLqZ^oZe_#U5B6O1!|{1ywRamYSyoV4LQ29xAz8_r`D;Taol9|z9baC^T!XTxb+ zi1bW!s*$;Y0zio2M}ki`4@?&DZ=VmD zKFL2#JWUbCQ0OLN%?|I)Y`XDERxr4)rZzDrL3NQ%bcf=tUU%MducV!nGhOt zY{tJK>$vwwm&d(inA{LYy7GCteq?XF8?ws3)GfkX=p93)mV9d0EC*WWb0j}H;vGA( z&pW2?&YDg7?n!g)-i6J3XAZw&e)Uz(vwCmPrv zJ$=OIKJ=Pz@-<)T9Y^ZC2i(hkck}b^Loa}waJ-}sjXBb2^|A-=k zYyK=cSo%NFUWDta#uLe#+=u2iAT~GaL&qHOE;Ia!-~ISe|KzU`qszwWUTZv|kj4}4 z;imx%pGwXf|0kJo5C1)A>eKq+bWL2|;(Zg`Lh@ujJQ+yNh9{1enl~q$ zDC+uIbM49%0_TPmW?#QP+FPsX=|6ZUGs!=p$2rbhOpnF*hb}mGMcPJMtLWC*zPD=l z1#?^Ke0|a*+gJz7oyn!CL8p;ioEog`PF|K8oDoS@rv_(6lXFsovxIwiCI%X)T}f(R zmTEOnGsrn-G&vV);p9xH3G;4!ZDgT7x{AgC?^x#NpJuZ;>`@E*A+Y>4 zUt?W!_wHpF#h#HD_~E0}Iqvq~LtW|KBO69`R8wOc(7wzkpTOYg;!1t!NCP@x=3U8e za_H$d+S8Mn3CXVVVnib8#Z*1@q*J(dditmS$)gVQ67--;NMO{gZGey8fDVFM0})`m zYHNN}iQIG2mGpS#9Ezph{1LOZ2DZ4=c8m|J)n&_Xb4by`U7}qtE?VH`2_d=$LBk9cU4!=Y`DMz4!Y%)?%Ef5L+BP`Qo_-r4zMh;#Xl)&W+R#8Sb%?8|-*$o< zpTw<-kbnPbzI1m;BcF`FY88y;3TCN-e@8)PHFT}#13hp2ceIbLy>6Kh{@dHqull#P zr9bj__|t#ds*l#!0^ZWT{4<(^WMUtqw!@z}%_ZJb>iL8|(Vl*m9LsIbII53EQ=)QSlbgxVT~JQt2$UmGjzBpA+vQDC{%*|c*_*lqQ(wORx_ezd?%H3K}1^gOru8crV1qD zonkZINRcC5@mQa71uv_TAycFGPI0_f>NNsA5HjN0*XL+R8-m@D(2d%%Nw1g3gMZ?p%PH(^poR$@TuG`kDumZ=oCW74tYD#GJ^__T!7u9Ye6E}M>o7C>E zAJ~PE(_w{u7iaFBBd7&PQj=o%MfDt)JJ--Vd(2>k{$4h_2ej@F*=#@2v)SxH!aC~QdQ1GsR`k;5LK;cRQkML!JAx}7AmSK zhZ)yZhTB2wAxgAFJLcq!gzyR)!R|>XMXNGS$l~SU*hw4Qiv}Q z)Adg$Mgjg#wov}E+&EB(FBB=C9kKFG+|~Q0#d#FW>(KpNDc;ZK5i3WRV>+C^p{>B^ z+E5f{8ovnNUWC^voX2^vGTn@`!{#TCE4NB~YTUjCob2;+LmI*9K`B2q{(lF2I{!wD79#p3ZRkts^k+4)x~Gqs<54+C|@H2wA%;cKXOJ`33>eaByPNo462z^lc=DgDHN9SwMKzp91&boTwye*Qk<=j0~fOKpB| zwzq_xl*H$WYW0z}{0$3AyUBjV!rVB@b{614GrwZ$ef@1^r(ZcMe@lbXcT3d!!xH!j zWrrKhzuiS-ob%(%3gyt7CG4ClfiHj^YFF`ns!99Y$~?WU1m0Q#4*{p^oATvtP>w#w zsK$M_-$z_N^_Q@-TjFT1x-LA=dQ94%I?nv9lHaZ-7KW;N0uL zHD+vdvV{B`>JJznj;nfkKDJ2WHUlbq18{9BEc6n%h(sf%CnQ2~Ghrt2Vm>7D+g1W* zUjUmzqDBI{K*F&=cWQ6R8>vwuTNpk-q-?X3x5x)Es66{t6F7J=rw zHu^WTtwULXm2e>-Uwnu_Yx`|Y{`SCa>(_5-=?HZAo7!6fYO{>b$GcZ(cS^tr2hCvd zmX{)#w%f4z1@AZl$prS?6z-NO6t#Bg6k>A63__QP1$u(fFl`Uo=JmE3W>YX>Y(%Iw zh13R~yqk+Xt&t|eQW1WUP?BtXbVxkbS2t={Yom>a>G%+ zkW{T5M1@%4&ZELIv<^|Ub_nsVq9TcHtKwlZ5gI_%or#1JRXdA9iKM)!ww5I}1kDgy zwk1%ofvL#o=WM~UUilQsTN|0EI_k7=rD$VQvG~*tU(;^t5}w4)J~P+}YQ`xK*NN)&)!eWpSf7ND3;~-)jmF z-3-EG8iP2?MtR~f*`+;3kGl7I!q8>T(y(qqOM~+;9PEpPP-_gfaPr6sEMvH4!h^A( z54ZR@qd2X>L2GH&=k*KI(-a&eTBcH#>*sav zI$#*`bNal_Van@uh{&YOF)RKOIa(WY{k$GxO7mYz>_5vfy%S}$)@Gj9O-wgQ?Wz7N zSac&pv1EN-UokzY1iAj=_S3wY^qZ6%ufv$~?+v7nS?84aeH|FZMEwkqU$3e48TC(l z;_J@X05W!cP3bW`&4P;ZvXAM*Mf$nPuA21z2mcUKq|au*QKZl7M5dVe6r^JRN0mOu zUua5P(Ua6TTjKaL^aL^_!uq`KWZJ=kiWb-Zk45^tK4mI*FxYGq*Z(glbK#(SfD*4a zcprPQJo8Lx-!f+ZIelL59;hd4`Tk;Yd7kxuiUR68TtBam`2PfGDlpu?SdXv&OVFkG zu|BV#kE@A!1Ip})^_l(>g?4@6Q_@N?rC27c$Mn}Iu9Tp;<3GPqyeKXf0{C1rnj{G{Iz*>}5v fO^p`USyagNvMk-EMIy53X&Ts(&RQgQF4q4a9ypZu literal 0 HcmV?d00001 diff --git a/aetime.c b/aetime.c index 1f80c730..e5ff8530 100644 --- a/aetime.c +++ b/aetime.c @@ -224,10 +224,10 @@ #include #define global static -#define uint unsigned int #define u8 uint8_t #define u32 uint32_t #define f32 float +#define uint u32 #define GenerateMagic(a, b, c, d) (((u32)(a) << 0) | ((u32)(b) << 8) | ((u32)(c) << 16) | ((u32)(d) << 24)) @@ -247,11 +247,6 @@ typedef struct timer_entry_array { } timer_entry_array; #pragma pack(pop) -// note(jax): Eventually support Mac/Linux... -#include -#include -#include - int StringLength(char* String) { int Count = 0; while (*String++) { @@ -283,11 +278,180 @@ bool StringsMatch(char* A, char* B) { global f32 GlobalFrequency; + #define COUNTERTOMS 1.f / (GlobalFrequency / 1000.f) #define COUNTERTOUS COUNTERTOMS * 1000.f #define COUNTERTONS COUNTERTOUS * 1000.f #define COUNTERTOS COUNTERTOMS / 1000.f + +#include +#include + +// +// PLATFORM SPECIFIC CODE +// + +// note(jax): Eventually support Mac... +#define BUILD_LINUX +#ifdef BUILD_LINUX +#include +#include +#include +#include +#include + +global void Usage(char** Args) { + fprintf(stdout, "Usage: %s --begin .aet [-v|--v|--verbose|-verbose]\n", Args[0]); + fprintf(stdout, " %s --end .aet [-v|--v|--verbose|-verbose]\n", Args[0]); +} + +// This function assumes FileName is a full path with an extension +char* GetBaseName(char* FileName) { + int BaseNameSize = 0; + char* BaseName = (char*)malloc(sizeof(char)*PATH_MAX); + char* BaseNameBegin = FileName; + char* BaseNameEnd = FileName + StringLength(FileName); + bool RightOfPeriod = false; + for (char* Scan = BaseNameBegin; *Scan; ++Scan) { + if ((Scan[0] == '\\') || (Scan[0] == '/')) { + BaseNameBegin = Scan + 1; + } + + if (Scan[0] == '.') { + BaseNameEnd = Scan; + RightOfPeriod = true; + } + else if (!RightOfPeriod) { + ++BaseNameSize; + } + } + + memcpy(BaseName, BaseNameBegin, BaseNameSize); + BaseName[BaseNameSize] = 0; + + return BaseName; +} + +uint64_t rdtsc(){ + unsigned int lo,hi; + __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); + return ((uint64_t)hi << 32) | lo; +} + +static uint64_t _get_tsc_ticks_since_reset_p() { + uint32_t countlo, counthi; + uint32_t chx; // Set to processor signature register - set to chip/socket & core ID by recent Linux kernels. + + __asm__ volatile("RDTSCP" : "=a" (countlo), "=d" (counthi), "=c" (chx)); + return (uint64_t(counthi) << 32) | countlo; +} + +#define BILLION 1E9 + +int main(int ArgCount, char** Args) { + bool IsVerbose = false; + if (StringsMatch(Args[3], "--verbose") || + StringsMatch(Args[3], "--v") || + StringsMatch(Args[3], "-verbose") || + StringsMatch(Args[3], "-v")) { + IsVerbose = true; + } + + char Path[PATH_MAX]; + sprintf(Path, "/tmp/"); + + struct timeval tv; + gettimeofday(&tv, nullptr); + double init_time_ = tv.tv_sec + tv.tv_usec*0.000001; + double init_tick_ = _get_tsc_ticks_since_reset_p(); + + gettimeofday(&tv, nullptr); + double seconds_since_epoch = tv.tv_sec + tv.tv_usec*0.000001; + + const double dTime = seconds_since_epoch - init_time_; + const uint64_t dTicks = _get_tsc_ticks_since_reset_p() - init_tick_; + GlobalFrequency = 1000000; + + if (ArgCount >= 3) { + if (StringsMatch(Args[1], "--begin")) { + char* FileName = Args[2]; + sprintf(Path + strlen(Path), "%s", FileName); + + FILE* Dest = fopen(Path, "wb"); + if (Dest) { + if (IsVerbose) { + printf("Writing to '%s'\n", Path); + } + + timer_file_header Header = {0}; + Header.Magic = AET_MAGIC_VALUE; + fwrite(&Header, sizeof(Header), 1, Dest); + + timer_file_entry Entry = {0}; + struct timespec Timer; + clock_gettime(CLOCK_MONOTONIC_RAW, &Timer); + Entry.Elapsed = (Timer.tv_nsec) + (Timer.tv_sec) * BILLION; + + printf("Compilation started for %s\n", GetBaseName(FileName)); + if (fwrite(&Entry, sizeof(Entry), 1, Dest) != 1) { + fprintf(stdout, "ERROR: Failed to append new start entry to file '%s'.\n", FileName); + } else { + fclose(Dest); + } + } else { + fprintf(stdout, "ERROR: Failed to open file '%s'.\n", FileName); + } + } else if (StringsMatch(Args[1], "--end")) { + char* FileName = Args[2]; + sprintf(Path + strlen(Path), "%s", FileName); + + FILE* Dest = fopen(Path, "rb"); + if (Dest) { + if (IsVerbose) { + printf("Reading from '%s'\n", Path); + } + + timer_file_header Header = {0}; + fread(&Header, sizeof(Header), 1, Dest); + if (IsVerbose) { + printf("struct timer_file_header {\n Magic: %u\n};\n", Header.Magic); + } + + timer_file_entry Entry = {0}; + if(fread(&Entry, sizeof(Entry), 1, Dest) == 1) { + struct timespec Timer; + clock_gettime(CLOCK_MONOTONIC_RAW, &Timer); + + f32 Elapsed = ((Timer.tv_nsec) + (Timer.tv_sec) * BILLION) - Entry.Elapsed; + f32 Milliseconds = Elapsed / 1000.f / 1000.f; + f32 Seconds = Milliseconds / 1000.f; + printf("Compilation ended: %f seconds\n", Seconds); + } else { + fprintf(stdout, "ERROR: Failed to read start entry from file '%s'.\n", FileName); + } + + fclose(Dest); + + if (remove(Path) != 0) { + fprintf(stdout, "ERROR: Failed to remove file '%s'.\n", FileName); + } + } else { + fprintf(stdout, "ERROR: Failed to open file '%s'.\n", FileName); + } + } else { + Usage(Args); + } + } else { + Usage(Args); + } + + return 1; +} + +#elif BUILD_WIN32 +#include + global void Usage(char** Args) { fprintf(stderr, "Usage: %s --begin .aet [-v|--v|--verbose|-verbose]\n", Args[0]); fprintf(stderr, " %s --end .aet [-v|--v|--verbose|-verbose]\n", Args[0]); @@ -409,4 +573,5 @@ int main(int ArgCount, char** Args) { } return 1; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/build.bat b/build.bat index 0ad06015..91d19467 100644 --- a/build.bat +++ b/build.bat @@ -1,5 +1,5 @@ @echo off REM -Zi for debugging -cl -nologo -FC -O2 -TC -EHsc aetime.c /link +cl -nologo -DBUILD_WIN32=1 -FC -O2 -TC -EHsc aetime.c /link @if ERRORLEVEL 1 exit /B 1 robocopy . ../ aetime.exe > nul \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 00000000..772a6bec --- /dev/null +++ b/build.sh @@ -0,0 +1,5 @@ +#!/bin/sh +set -eu +CXX=${CXX:-clang++} + +${CXX} $* -Wwritable-strings -DBUILD_LINUX=1 -I. -O3 -o aetime aetime.c \ No newline at end of file From 38f463a111f99efca269a201f46b632b1bed9938 Mon Sep 17 00:00:00 2001 From: jaxne Date: Mon, 29 Jun 2020 20:27:25 -0600 Subject: [PATCH 5/5] Prep for move --- aetime => timer/aetime | Bin aetime.c => timer/aetime.c | 0 aetime.exe => timer/aetime.exe | Bin build.bat => timer/build.bat | 0 build.sh => timer/build.sh | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename aetime => timer/aetime (100%) rename aetime.c => timer/aetime.c (100%) rename aetime.exe => timer/aetime.exe (100%) rename build.bat => timer/build.bat (100%) rename build.sh => timer/build.sh (100%) diff --git a/aetime b/timer/aetime similarity index 100% rename from aetime rename to timer/aetime diff --git a/aetime.c b/timer/aetime.c similarity index 100% rename from aetime.c rename to timer/aetime.c diff --git a/aetime.exe b/timer/aetime.exe similarity index 100% rename from aetime.exe rename to timer/aetime.exe diff --git a/build.bat b/timer/build.bat similarity index 100% rename from build.bat rename to timer/build.bat diff --git a/build.sh b/timer/build.sh similarity index 100% rename from build.sh rename to timer/build.sh