{"id":18282569,"url":"https://github.com/rafael-santiago/hysplex","last_synced_at":"2026-04-18T10:33:59.109Z","repository":{"id":80005661,"uuid":"334781996","full_name":"rafael-santiago/hysplex","owner":"rafael-santiago","description":"A tiny, well-contained and well-simple C library to help you measure function implementations performance and choose the best one.","archived":false,"fork":false,"pushed_at":"2021-02-16T19:05:17.000Z","size":50,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-09T05:29:39.985Z","etag":null,"topics":["benchmark","c","c99","cpp","optimization-helper","optimzation"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-4-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rafael-santiago.png","metadata":{"files":{"readme":"README","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-31T23:46:15.000Z","updated_at":"2023-03-05T02:51:07.000Z","dependencies_parsed_at":"2023-05-26T04:15:10.953Z","dependency_job_id":null,"html_url":"https://github.com/rafael-santiago/hysplex","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/rafael-santiago/hysplex","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafael-santiago%2Fhysplex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafael-santiago%2Fhysplex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafael-santiago%2Fhysplex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafael-santiago%2Fhysplex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rafael-santiago","download_url":"https://codeload.github.com/rafael-santiago/hysplex/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rafael-santiago%2Fhysplex/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31965957,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["benchmark","c","c99","cpp","optimization-helper","optimzation"],"created_at":"2024-11-05T13:05:36.542Z","updated_at":"2026-04-18T10:33:59.064Z","avatar_url":"https://github.com/rafael-santiago.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"_     _ __   __  _____   _____          ______ _     _\n|_____|   \\_/   |_____  |_____] |      |______  \\___/\n|     |    |     _____| |       |_____ |______ _/   \\_\n-------------------------------------------------------\n\n\nWhat is it about?\n-----------------\n\nHysplex is a C library that helps you measure performance of different\nimplementations of a function.\n\nWhat is the easiest way of cloning it?\n--------------------------------------\n\n_ git clone https://github.com/rafael-santiago/hysplex hysplex --recursive\n\nHow can I build it?\n-------------------\n\nYou need to use my personal build system called Hefesto\n\u003chttps://github.com/rafael-santiago/hefesto\u003e.\n\nAfter following the steps to make Hefesto work on your environment,\nyou need to move to src sub-directory and invoke Hefesto from there.\n\n_ cd hysplex/src\n_ hefesto\n\nIf all worked you will get hysplex ar file at '../lib/libhysplex.a'.\n\nUsing hysplex\n-------------\n\nHysplex is based on an internal DSL. The following code will able to\nmeasure the performance of two different implementations of a simple\ninteger sum function:\n\n    #include \u003chysplex.h\u003e\n    #include \u003cstdio.h\u003e\n    #include \u003cunistd.h\u003e\n\n    static int plain_sum(const int a, const int b) {\n        return a + b;\n    }\n\n    static int delayed_sum(const int a, const int b) {\n        usleep(1);\n        return a + b;\n    }\n\n    HYSPLEX_EVAL_PAIR(100000, 1, {}, {}, plain_sum, delayed_sum, 1, 2);\n\nThe only DSL statement that is necessary to do the task is HYSPLEX_EVAL_PAIR.\n\nHYSPLEX_EVAL_PAIR allows you measure performance of two functions. It expects:\n\n    - A default number of iterations (how many times those functions will run).\n\n    - If you want or not warm up (run functions without any benchmarking just\n      to warm up cache).\n\n    - A set of pre statements to execute before calling the functions.\n\n    - A set of post statements to execute after calling the functions.\n\n    - The two functions.\n\n    - The parameter list that must be passed to those functions.\n\nIn order to compile you need to include -I\u003cdirectory path to hysplex.h\u003e,\n-L\u003cdirectory path to libhysplex.a\u003e -lhysplex. E.g.:\n\n_ gcc -I~/hysplex/src -L~/hysplex/lib eval_pair.c -oeval-pair -lhysplex\n\nAfter compiling the source you will get an application suitable to\nmeasure your functions and present to you the results of all benchmarking.\n\nAll you should do is:\n\n_ ./eval-pair\n\nYou will get a thing similar to this:\n\n    == Hysplex final stats\n\n    == Functions 'plain_sum' and 'delayed_sum' were executed 100000 time(s).\n    == Function 'plain_sum' has won 99963 time(s).\n    == Function 'delayed_sum' has won 144 time(s).\n    == Total of tied executions: 53.\n    == Total of iterations with a winner: 99947\n    == The average execution time of function 'plain_sum' was about 0.000000 secs.\n    == The average execution time of function 'delayed_sum' was about 0.000011 secs.\n\n    == The winner function is 'plain_sum'.\n\n    == Chi-square = 99692.192 (certainty = 95%), 'plain_sum' is statistically faster than 'delayed_sum'.\n\nAs you can see, Hysplex figured out that 'plain_sum' is really faster than 'delayed_sum' (of course).\nThe nice thing here is that a Chi-square test was executed against the benchmarking data in order to\nensure relevance or not between the found performance difference.\n\nYou can configure at run-time Chi-square's certainty by passing to your benchmarking executable the\noption '--certainty-perc=\u003cpercentual\u003e'. The percentual values can be: 90, 95 (default), 97, 99 and 100.\n\nYou can also overwrite the total of iterations passing the option '--iterations=\u003cvalue\u003e'.\n\nIf you want to divert the results to a file use the option '--out=\u003cfile path\u003e'. If the provided file path provided\nalready exists the result data will be appended to this file.\n\nSometimes you will implement a bunch of different implementations of the same function. Test them paired\ncan be tedious when using HYSPLEX_EVAIL_PAIR besides error prone (repetitive tasks delegated to Humans\nlead to errors, avoid doing this, better using your brain to think...)\n\nTo test a group of functions you should use HYSPLEX_EVAL_GROUP. When using eval group DSL statement\nyou need to pass a function group declared by using HYSPLEX_FUNCTION_GROUP. Take a look at the\nfollowing code:\n\n    #include \u003chysplex.h\u003e\n    #include \u003csys/stat.h\u003e\n    #include \u003cfcntl.h\u003e\n\n    int stat_based_file_exists(const char *filepath) {\n        if (filepath == NULL) {\n            return 0;\n        }\n        struct stat st;\n        return (stat(filepath, \u0026st) == 0);\n    }\n\n    int fopen_based_file_exists(const char *filepath) {\n        if (filepath == NULL) {\n            return 0;\n        }\n        FILE *fp;\n        int retval = ((fp = fopen(filepath, \"r\")) != NULL);\n        if (retval) {\n            fclose(fp);\n        }\n        return retval;\n    }\n\n    int open_based_file_exists(const char *filepath) {\n        if (filepath == NULL) {\n            return 0;\n        }\n        int fd;\n        int retval = ((fd = open(filepath, O_RDONLY)) != -1);\n        if (retval \u003e -1) {\n            close(fd);\n        }\n        return retval;\n    }\n\n    HYSPLEX_FUNCTION_GROUP_BEGIN(func_group)\n        HYSPLEX_REGISTER_FUNCTION(fopen_based_file_exists),\n        HYSPLEX_REGISTER_FUNCTION(stat_based_file_exists),\n        HYSPLEX_REGISTER_FUNCTION(open_based_file_exists),\n    HYSPLEX_FUNCTION_GROUP_END\n\n    HYSPLEX_EVAL_GROUP(100000, 1,\n                       {\n                            FILE *fp = fopen(\"test.dat\", \"wb\");\n                            fclose(fp);\n                       },\n                       {\n                            remove(\"test.dat\");\n                       },\n                       func_group, \"test.dat\");\n\nHYSPLEX_EVAL_GROUP expects the same arguments expected by HYSPLEX_EVAL_PAIR,\nexcepting the two functions. HYSPLEX_EVAL_GROUP expects the previous declared\nfunction group, where you have registered all functions that will run this\n\"marathon\".\n\nTo compile:\n\n_ gcc -I~/hysplex/src -L~/hysplex/lib eval_group.c -oeval-group -lhysplex\n\nTo run:\n\n_ ./eval-group\n\n    == Hysplex intermediate stats\n\n    == Functions 'fopen_based_file_exists' and 'stat_based_file_exists' were executed 100000 time(s).\n    == Function 'fopen_based_file_exists' has won 43313 time(s).\n    == Function 'stat_based_file_exists' has won 99365 time(s).\n    == Total of tied executions: 21339.\n    == Total of iterations with a winner: 78661\n    == The average execution time of function 'fopen_based_file_exists' was about 0.000002 secs.\n    == The average execution time of function 'stat_based_file_exists' was about 0.000001 secs.\n\n    == The winner function is 'stat_based_file_exists'.\n\n    == Chi-square = 45731.278 (certainty = 95%), 'stat_based_file_exists' is statistically faster than 'fopen_based_file_exists'.\n\n    == Hysplex final stats\n\n    == Functions 'stat_based_file_exists' and 'open_based_file_exists' were executed 100000 time(s).\n    == Function 'stat_based_file_exists' has won 84572 time(s).\n    == Function 'open_based_file_exists' has won 61371 time(s).\n    == Total of tied executions: 22971.\n    == Total of iterations with a winner: 77029\n    == The average execution time of function 'stat_based_file_exists' was about 0.000001 secs.\n    == The average execution time of function 'open_based_file_exists' was about 0.000001 secs.\n\n    == The winner function is 'stat_based_file_exists'.\n\n    == Chi-square = 13839.709 (certainty = 95%), 'stat_based_file_exists' is statistically faster than 'open_based_file_exists'.\n\nAs you can see, use stat() to check file existence is the fastest way among the three tested ways.\n\nHysplex also gives you the tip when performance is a pointless subject. Let's consider the implementation of the two\nfollowing functions:\n\n    static int sum_with_copy(const int a, const int b) {\n        int aa = a;\n        int bb = b;\n        return aa + bb;\n    }\n\n    static int sum_with_xor_swap(const int a, const int b) {\n        int aa = a ^ b;\n        int bb = aa ^ b;\n        aa ^= bb;\n        return aa + bb;\n    }\n\nWould xoring swap faster than a copy?\n\nWell, now getting the answer is a straightforward task, look:\n\n    HYSPLEX_EVAL_PAIR(100000, 1, {}, {}, sum_with_copy, sum_with_xor_swap, 1, 2);\n\nTo compile:\n\n_ gcc -I~/hysplex/src -L~/hysplex/lib eval_pair_inconclusive.c -oeval-pair-inconclusive -lhysplex\n\nTo run:\n\n_ ./eval-pair-inconclusive\n\nhysplex warn: The evaluated performances are inconclusive. They are almost the same in performance. A bias was detected.\n              The second function seems to take advantage from the first, probably due to CPU cache.\n              You should take into consideration other aspects than performance to pick one. It is up to you!\n\nThe result of \"eval-pair-inconclusive\" can vary from a computer to another. Sometimes Hysplex can tell you that the\ntwo functions are the same in performance even not being detected any execution bias. Well, even so, it is inconclusive\nanyway.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafael-santiago%2Fhysplex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frafael-santiago%2Fhysplex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frafael-santiago%2Fhysplex/lists"}