├── README.md ├── classification ├── benchmark_examples.ipynb ├── dataset_visualization.ipynb ├── main.py ├── noisy.py ├── pagesize.py └── utils │ ├── __init__.py │ ├── cache.py │ ├── preparation.py │ └── uarch.py ├── data └── cpus.csv ├── native ├── Makefile ├── associativity.c ├── cache_profile.c ├── list_cache.c ├── loadbuffer.c ├── pagesize.c ├── prefetch.c ├── tlbsize.c └── utils.h └── web ├── cpuprofiler ├── __init__.py ├── asgi.py ├── middleware.py ├── settings.py ├── static │ ├── admin │ │ ├── css │ │ │ ├── autocomplete.css │ │ │ ├── base.css │ │ │ ├── changelists.css │ │ │ ├── dashboard.css │ │ │ ├── fonts.css │ │ │ ├── forms.css │ │ │ ├── login.css │ │ │ ├── nav_sidebar.css │ │ │ ├── responsive.css │ │ │ ├── responsive_rtl.css │ │ │ ├── rtl.css │ │ │ ├── vendor │ │ │ │ └── select2 │ │ │ │ │ ├── LICENSE-SELECT2.md │ │ │ │ │ ├── select2.css │ │ │ │ │ └── select2.min.css │ │ │ └── widgets.css │ │ ├── fonts │ │ │ ├── LICENSE.txt │ │ │ ├── README.txt │ │ │ ├── Roboto-Bold-webfont.woff │ │ │ ├── Roboto-Light-webfont.woff │ │ │ └── Roboto-Regular-webfont.woff │ │ ├── img │ │ │ ├── LICENSE │ │ │ ├── README.txt │ │ │ ├── calendar-icons.svg │ │ │ ├── gis │ │ │ │ ├── move_vertex_off.svg │ │ │ │ └── move_vertex_on.svg │ │ │ ├── icon-addlink.svg │ │ │ ├── icon-alert.svg │ │ │ ├── icon-calendar.svg │ │ │ ├── icon-changelink.svg │ │ │ ├── icon-clock.svg │ │ │ ├── icon-deletelink.svg │ │ │ ├── icon-no.svg │ │ │ ├── icon-unknown-alt.svg │ │ │ ├── icon-unknown.svg │ │ │ ├── icon-viewlink.svg │ │ │ ├── icon-yes.svg │ │ │ ├── inline-delete.svg │ │ │ ├── search.svg │ │ │ ├── selector-icons.svg │ │ │ ├── sorting-icons.svg │ │ │ ├── tooltag-add.svg │ │ │ └── tooltag-arrowright.svg │ │ └── js │ │ │ ├── SelectBox.js │ │ │ ├── SelectFilter2.js │ │ │ ├── actions.js │ │ │ ├── admin │ │ │ ├── DateTimeShortcuts.js │ │ │ └── RelatedObjectLookups.js │ │ │ ├── autocomplete.js │ │ │ ├── calendar.js │ │ │ ├── cancel.js │ │ │ ├── change_form.js │ │ │ ├── collapse.js │ │ │ ├── core.js │ │ │ ├── inlines.js │ │ │ ├── jquery.init.js │ │ │ ├── nav_sidebar.js │ │ │ ├── popup_response.js │ │ │ ├── prepopulate.js │ │ │ ├── prepopulate_init.js │ │ │ ├── urlify.js │ │ │ └── vendor │ │ │ ├── jquery │ │ │ ├── LICENSE.txt │ │ │ ├── jquery.js │ │ │ └── jquery.min.js │ │ │ ├── select2 │ │ │ ├── LICENSE.md │ │ │ ├── i18n │ │ │ │ ├── af.js │ │ │ │ ├── ar.js │ │ │ │ ├── az.js │ │ │ │ ├── bg.js │ │ │ │ ├── bn.js │ │ │ │ ├── bs.js │ │ │ │ ├── ca.js │ │ │ │ ├── cs.js │ │ │ │ ├── da.js │ │ │ │ ├── de.js │ │ │ │ ├── dsb.js │ │ │ │ ├── el.js │ │ │ │ ├── en.js │ │ │ │ ├── es.js │ │ │ │ ├── et.js │ │ │ │ ├── eu.js │ │ │ │ ├── fa.js │ │ │ │ ├── fi.js │ │ │ │ ├── fr.js │ │ │ │ ├── gl.js │ │ │ │ ├── he.js │ │ │ │ ├── hi.js │ │ │ │ ├── hr.js │ │ │ │ ├── hsb.js │ │ │ │ ├── hu.js │ │ │ │ ├── hy.js │ │ │ │ ├── id.js │ │ │ │ ├── is.js │ │ │ │ ├── it.js │ │ │ │ ├── ja.js │ │ │ │ ├── ka.js │ │ │ │ ├── km.js │ │ │ │ ├── ko.js │ │ │ │ ├── lt.js │ │ │ │ ├── lv.js │ │ │ │ ├── mk.js │ │ │ │ ├── ms.js │ │ │ │ ├── nb.js │ │ │ │ ├── ne.js │ │ │ │ ├── nl.js │ │ │ │ ├── pl.js │ │ │ │ ├── ps.js │ │ │ │ ├── pt-BR.js │ │ │ │ ├── pt.js │ │ │ │ ├── ro.js │ │ │ │ ├── ru.js │ │ │ │ ├── sk.js │ │ │ │ ├── sl.js │ │ │ │ ├── sq.js │ │ │ │ ├── sr-Cyrl.js │ │ │ │ ├── sr.js │ │ │ │ ├── sv.js │ │ │ │ ├── th.js │ │ │ │ ├── tk.js │ │ │ │ ├── tr.js │ │ │ │ ├── uk.js │ │ │ │ ├── vi.js │ │ │ │ ├── zh-CN.js │ │ │ │ └── zh-TW.js │ │ │ ├── select2.full.js │ │ │ └── select2.full.min.js │ │ │ └── xregexp │ │ │ ├── LICENSE.txt │ │ │ ├── xregexp.js │ │ │ └── xregexp.min.js │ ├── all │ │ ├── basic.js │ │ ├── buffer.js │ │ ├── cores.js │ │ └── performance.js │ ├── buffer │ │ ├── load.js │ │ ├── loadWorker.js │ │ └── store.js │ ├── cache │ │ ├── assoFinder.js │ │ ├── cacheAssociativity.js │ │ ├── cacheSize.js │ │ └── sizeFinder.js │ ├── favicon.ico │ ├── main.js │ ├── misc │ │ ├── bits │ │ │ └── bits.js │ │ ├── cores │ │ │ ├── cores.js │ │ │ └── worker.js │ │ ├── pagesize │ │ │ ├── pageSize.js │ │ │ └── pagesizeFinder.js │ │ ├── prefetcher │ │ │ ├── prefetch.js │ │ │ └── prefetchWorker.js │ │ └── timer │ │ │ └── precision.js │ ├── performance │ │ ├── memory.js │ │ ├── memoryWorker.js │ │ ├── performance.js │ │ ├── performanceMulti.js │ │ └── performanceWorker.js │ ├── tlb │ │ ├── tlbSize.js │ │ └── tlbsizeFinder.js │ ├── utils │ │ ├── clockWorker.js │ │ └── profilerUtils.js │ ├── vendor │ │ ├── bootstrap │ │ │ ├── css │ │ │ │ ├── bootstrap-grid.css │ │ │ │ ├── bootstrap-grid.css.map │ │ │ │ ├── bootstrap-grid.min.css │ │ │ │ ├── bootstrap-grid.min.css.map │ │ │ │ ├── bootstrap-reboot.css │ │ │ │ ├── bootstrap-reboot.css.map │ │ │ │ ├── bootstrap-reboot.min.css │ │ │ │ ├── bootstrap-reboot.min.css.map │ │ │ │ ├── bootstrap.css │ │ │ │ ├── bootstrap.css.map │ │ │ │ ├── bootstrap.min.css │ │ │ │ └── bootstrap.min.css.map │ │ │ └── js │ │ │ │ ├── bootstrap.bundle.copy.js │ │ │ │ ├── bootstrap.bundle.js │ │ │ │ ├── bootstrap.bundle.js.map │ │ │ │ ├── bootstrap.bundle.min.js │ │ │ │ ├── bootstrap.bundle.min.js.map │ │ │ │ ├── bootstrap.js │ │ │ │ ├── bootstrap.js.map │ │ │ │ ├── bootstrap.min.js │ │ │ │ └── bootstrap.min.js.map │ │ ├── canvasjs │ │ │ └── canvasjs.min.js │ │ └── jquery │ │ │ └── jquery.min.js │ └── wasm │ │ ├── bits.wasm │ │ ├── bits.wat │ │ ├── clock.wasm │ │ ├── clock.wat │ │ ├── loadbuffer.wasm │ │ ├── loadbuffer.wat │ │ ├── pagesize.wasm │ │ ├── pagesize.wat │ │ ├── prefetch.wasm │ │ ├── prefetch.wat │ │ ├── size.wasm │ │ ├── size.wat │ │ └── storebuffer.wat ├── urls.py └── wsgi.py ├── manage.py ├── navigation ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── templates │ ├── base.html │ ├── home.html │ ├── landing.html │ ├── overview.html │ └── problem.html ├── tests.py ├── urls.py └── views.py ├── plot ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── tests.py ├── urls.py └── views.py ├── profilers ├── __init__.py ├── admin.py ├── apps.py ├── migrations │ └── __init__.py ├── models.py ├── templates │ ├── buffer │ │ ├── load.html │ │ └── store.html │ ├── cache │ │ ├── associativity.html │ │ └── size.html │ ├── misc │ │ ├── bits.html │ │ ├── cores.html │ │ ├── pagesize.html │ │ ├── prefetcher.html │ │ └── timer.html │ ├── performance │ │ ├── memory.html │ │ ├── multi.html │ │ └── single.html │ ├── profiler.html │ └── tlb │ │ └── size.html ├── tests.py ├── urls.py └── views.py ├── requirements.txt └── upload ├── __init__.py ├── admin.py ├── apps.py ├── migrations └── __init__.py ├── models.py ├── tests.py ├── urls.py └── views.py /classification/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .cache import * 2 | from .preparation import * 3 | from .uarch import * -------------------------------------------------------------------------------- /classification/utils/uarch.py: -------------------------------------------------------------------------------- 1 | def replace_uarch_by_base(uarchs): 2 | # Skylake 3 | uarchs = list(map(lambda x: "Skylake" if x == "Kaby Lake" else x, uarchs)) 4 | uarchs = list(map(lambda x: "Skylake" if x == "Coffee Lake" else x, uarchs)) 5 | uarchs = list(map(lambda x: "Skylake" if x == "Comet Lake" else x, uarchs)) 6 | uarchs = list(map(lambda x: "Skylake" if x == "Whiskey Lake" else x, uarchs)) 7 | 8 | # Haswell 9 | uarchs = list(map(lambda x: "Haswell" if x == "Broadwell" else x, uarchs)) 10 | 11 | # Sandy Bridge 12 | uarchs = list(map(lambda x: "Sandy Bridge" if x == "Ivy Bridge" else x, uarchs)) 13 | 14 | # Sunny Cove 15 | uarchs = list(map(lambda x: "Sunny Cove" if x == "Ice Lake" else x, uarchs)) 16 | 17 | # Willow Cove 18 | uarchs = list(map(lambda x: "Willow Cove" if x == "Tiger Lake" else x, uarchs)) 19 | 20 | return uarchs -------------------------------------------------------------------------------- /native/Makefile: -------------------------------------------------------------------------------- 1 | # -masm=intel 2 | loadbuffer: 3 | gcc -O0 -Wall -Wpedantic -o loadbuffer.run loadbuffer.c 4 | 5 | prefetch: 6 | gcc -O0 -Wall -Wpedantic -o prefetch.run prefetch.c 7 | 8 | tlbsize: 9 | gcc -O0 -Wall -Wpedantic -o tlbsize.run tlbsize.c 10 | 11 | pagesize: 12 | gcc -O0 -Wall -Wpedantic -o pagesize.run pagesize.c 13 | 14 | associativity: 15 | gcc -O0 -Wall -Wpedantic -o associativity.run associativity.c 16 | 17 | list_cache: 18 | gcc -O0 -Wall -Wpedantic -o list_cache.run list_cache.c 19 | 20 | clean: 21 | rm *.run -------------------------------------------------------------------------------- /native/associativity.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define N 32 * MB 9 | 10 | struct elem { 11 | struct elem *next; 12 | }; 13 | 14 | int main() { 15 | srand ( time(NULL) ); 16 | for (uint64_t s = 1; s < 64; s += 1) { 17 | uint64_t SIZE = s * KB; 18 | struct elem * array = malloc(SIZE); 19 | 20 | for (size_t i = 0; i < (SIZE - 1) / sizeof(struct elem); ++i) array[i].next = &array[i + 1]; 21 | array[(SIZE - 1) / sizeof(struct elem)].next = array; 22 | 23 | // https://stackoverflow.com/a/13482822/13125945 24 | struct elem* pNext = NULL; 25 | struct elem* pHead = NULL; 26 | struct elem* pTail = NULL; 27 | int i = 0; 28 | // reset .next to NULL 29 | memset(array, 0, SIZE); 30 | pHead = &array[ rand() % (SIZE / sizeof(struct elem))]; 31 | pTail = pHead; 32 | for (i = 0; i < (SIZE - 1) / sizeof(struct elem); ++i) 33 | { 34 | pTail->next = pTail; 35 | while ((pNext = &array[ rand() % (SIZE / sizeof(struct elem)) ]) && pNext->next); 36 | pTail->next = pNext; 37 | pTail = pNext; 38 | } 39 | pTail->next = pHead; 40 | 41 | // 42 | 43 | uint64_t start = rdtsc(); 44 | int64_t dummy = 0; 45 | struct elem * current = pHead; 46 | for (size_t n = 0; n < N; ++n) { 47 | dummy += (int64_t)current; 48 | current = current->next; 49 | } 50 | uint64_t end = rdtsc(); 51 | printf("(%ld,%ld),\n", SIZE / KB, (end - start)); 52 | 53 | free(array); 54 | } 55 | } -------------------------------------------------------------------------------- /native/cache_profile.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "utils.h" 6 | 7 | #define KB 1024 8 | #define MB 1024 * 1024 9 | 10 | int main() { 11 | unsigned int steps = 256 * 1024 * 1024; 12 | static int arr[24 * MB]; 13 | unsigned long long lengthMod; 14 | unsigned int i; 15 | double timeTaken; 16 | clock_t start; 17 | unsigned long long sizes[] = { 18 | 1 * KB, 4 * KB, 8 * KB, 16 * KB, 32 * KB, 64 * KB, 128 * KB, 256 * KB, 19 | 512 * KB, 1 * MB, 2 * MB, 4 * MB, 6 * MB, 8 * MB, 10 * MB, 12 * MB, 20 | 14 * MB, 16 * MB, 18 * MB, 20 * MB, 22 * MB, 24 * MB 21 | }; 22 | int s; 23 | 24 | // for each size to test for ... 25 | for (s = 0; s < sizeof(sizes)/sizeof(unsigned long long); s++) { 26 | int lengthMod = sizes[s] - 1; 27 | uint64_t start = rdtsc(); 28 | for (int i = 0; i < steps; i++) { 29 | arr[(i * 16) & lengthMod]++; 30 | } 31 | uint64_t end = rdtsc(); 32 | printf("(%lld,%ld),", sizes[s] / KB, end - start); 33 | } 34 | 35 | return 0; 36 | } 37 | -------------------------------------------------------------------------------- /native/list_cache.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define N 32 * MB 9 | 10 | struct elem { 11 | struct elem *next; 12 | }; 13 | 14 | int main() { 15 | srand ( time(NULL) ); 16 | for (uint64_t s = 1; s < 512; s += 1) { 17 | uint64_t SIZE = s * KB; 18 | struct elem * array = malloc(SIZE); 19 | 20 | for (size_t i = 0; i < (SIZE - 1) / sizeof(struct elem); ++i) array[i].next = &array[i + 1]; 21 | array[(SIZE - 1) / sizeof(struct elem)].next = array; 22 | 23 | // https://stackoverflow.com/a/13482822/13125945 24 | struct elem* pNext = NULL; 25 | struct elem* pHead = NULL; 26 | struct elem* pTail = NULL; 27 | int i = 0; 28 | // reset .next to NULL 29 | memset(array, 0, SIZE); 30 | pHead = &array[ rand() % (SIZE / sizeof(struct elem))]; 31 | pTail = pHead; 32 | for (i = 0; i < (SIZE - 1) / sizeof(struct elem); ++i) 33 | { 34 | pTail->next = pTail; 35 | while ((pNext = &array[ rand() % (SIZE / sizeof(struct elem)) ]) && pNext->next); 36 | pTail->next = pNext; 37 | pTail = pNext; 38 | } 39 | pTail->next = pHead; 40 | 41 | // 42 | 43 | uint64_t start = rdtsc(); 44 | int64_t dummy = 0; 45 | struct elem * current = pHead; 46 | for (size_t n = 0; n < N; ++n) { 47 | dummy += (int64_t)current; 48 | current = current->next; 49 | } 50 | uint64_t end = rdtsc(); 51 | printf("(%ld,%ld),\n", SIZE / KB, (end - start)); 52 | 53 | free(array); 54 | } 55 | } -------------------------------------------------------------------------------- /native/pagesize.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX_SIZE 256 * KB 8 | #define STEPS 8192 9 | 10 | // 4 KB, 8 KB, 64 KB, 256 KB, 1 MB, 2 MB, 4 MB, 16 MB, 256 MB 11 | 12 | int main() { 13 | uint32_t * buffer = malloc(sizeof(uint64_t) * MAX_SIZE); 14 | 15 | for (uint64_t i = 0; i <= STEPS; i += 8) { 16 | 17 | uint64_t start = rdtsc(); 18 | uint32_t tmp = buffer[i]; 19 | uint64_t end = rdtsc(); 20 | printf("(%ld,%ld),\n", i, end - start); 21 | 22 | } 23 | 24 | free(buffer); 25 | } -------------------------------------------------------------------------------- /native/prefetch.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX_SIZE KB * MB 8 | #define STEPS 20 * MB 9 | #define PAGESIZE 4096 10 | #define ENTRIES MB 11 | #define FENCE 200 12 | 13 | 14 | void shuffle(int *array, size_t n) { 15 | if (n > 1) 16 | { 17 | size_t i; 18 | for (i = 0; i < n - 1; i++) 19 | { 20 | size_t j = i + rand() / (RAND_MAX / (n - i) + 1); 21 | int t = array[j]; 22 | array[j] = array[i]; 23 | array[i] = t; 24 | } 25 | } 26 | } 27 | 28 | int main() { 29 | uint64_t randomStuff = 0; 30 | uint8_t * buffer = malloc(sizeof(uint8_t) * MAX_SIZE); 31 | uint8_t * buffer2 = malloc(sizeof(uint8_t) * MAX_SIZE); 32 | int * indices = malloc(sizeof(int) * ENTRIES); 33 | 34 | for (uint32_t j = 0; j < ENTRIES; j++) { 35 | indices[j] = j * 256; 36 | } 37 | 38 | shuffle(indices, ENTRIES); 39 | 40 | //touch 41 | for (uint32_t j = 0; j < ENTRIES; j++) { 42 | uint32_t index = j * 256 + 128; 43 | buffer[index] = j; 44 | buffer2[index] = j + 1; 45 | } 46 | 47 | uint64_t time = 0; 48 | uint64_t start; 49 | 50 | for (uint64_t step = 0; step < ENTRIES; step++) { 51 | // flush(buffer + indices[ step ]); 52 | // flush(buffer + indices[ step ] + 64); 53 | // for (uint64_t i = 0; i < FENCE; i++) { 54 | // randomStuff += 1; 55 | // } 56 | maccess(buffer + indices[ step ]); 57 | start = rdtsc(); 58 | maccess(buffer + indices[ step ] + 64); 59 | time += rdtsc() - start; 60 | } 61 | 62 | printf("Time A - %ld\n", time); 63 | 64 | time = 0; 65 | 66 | for (uint64_t step = 0; step < ENTRIES; step++) { 67 | // flush(buffer2 + indices[ step ]); 68 | // flush(buffer2 + indices[ step ] + 16); 69 | // for (uint64_t i = 0; i < FENCE; i++) { 70 | // randomStuff += 1; 71 | // } 72 | maccess(buffer2 + indices[ step ]); 73 | start = rdtsc(); 74 | maccess(buffer2 + indices[ step ] + 16); 75 | time += rdtsc() - start; 76 | } 77 | 78 | printf("Time B - %ld\n", time); 79 | 80 | free(indices); 81 | free(buffer); 82 | free(buffer2); 83 | 84 | } -------------------------------------------------------------------------------- /native/tlbsize.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX_SIZE KB * MB 8 | #define STEPS 256 9 | #define PAGES 256 10 | #define PAGESIZE 4096 11 | #define LARGESTEPS 256 * MB 12 | 13 | // 4 KB, 8 KB, 64 KB, 256 KB, 1 MB, 2 MB, 4 MB, 16 MB, 256 MB 14 | 15 | static inline uint32_t mlog2(const uint32_t x) { 16 | uint32_t y; 17 | asm ( "\tbsr %1, %0\n" 18 | : "=r"(y) 19 | : "r" (x) 20 | ); 21 | return y; 22 | } 23 | 24 | void shuffle(int *array, size_t n) 25 | { 26 | if (n > 1) 27 | { 28 | size_t i; 29 | for (i = 0; i < n - 1; i++) 30 | { 31 | size_t j = i + rand() / (RAND_MAX / (n - i) + 1); 32 | int t = array[j]; 33 | array[j] = array[i]; 34 | array[i] = t; 35 | } 36 | } 37 | } 38 | 39 | int main() { 40 | uint8_t * buffer = malloc(sizeof(uint8_t) * MAX_SIZE); 41 | int * indices = malloc(sizeof(int) * 1); 42 | 43 | for (uint32_t page = 1; page <= PAGES; page++) { 44 | 45 | indices = realloc(indices, sizeof(int) * page); 46 | 47 | for (uint32_t j = 0; j < page; j++) { 48 | indices[j] = j * PAGESIZE; 49 | } 50 | 51 | //shuffle(indices, page); 52 | 53 | // put in tlb 54 | for (uint32_t j = 0; j < page; j++) { 55 | buffer[indices[j]] = j; 56 | } 57 | 58 | // uint64_t minimum = INT64_MAX; 59 | // for (uint64_t step = 0; step < STEPS; step++) { 60 | // uint64_t maximum = 0; 61 | // for (uint32_t j = 0; j < page; j++) { 62 | // flush(&buffer[indices[j]]); 63 | // uint64_t start = rdtsc(); 64 | // maccess(buffer + indices[j]); 65 | // uint64_t time = rdtsc() - start; 66 | // if (time > maximum) maximum = time; 67 | // } 68 | // if (minimum > maximum) minimum = maximum; 69 | // } 70 | 71 | // printf("(%d,%ld),\n", page, minimum); 72 | 73 | uint64_t start = rdtsc(); 74 | 75 | for (uint64_t step = 0; step < LARGESTEPS; step++) { 76 | maccess(buffer + indices[step % page]); 77 | } 78 | 79 | uint64_t time = rdtsc() - start; 80 | 81 | printf("(%d,%ld),\n", page, time); 82 | 83 | } 84 | 85 | free(indices); 86 | free(buffer); 87 | } -------------------------------------------------------------------------------- /native/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef NATIVE_UTILS_H 2 | #define NATIVE_UTILS_H 3 | 4 | #include 5 | 6 | #define KB 1024 7 | #define MB 1024 * 1024 8 | 9 | // src: https://github.com/IAIK/flush_flush/blob/master/sc/cacheutils.h 10 | uint64_t rdtsc() { 11 | uint64_t a, d; 12 | asm volatile ("mfence"); 13 | asm volatile ("rdtsc" : "=a" (a), "=d" (d)); 14 | a = (d<<32) | a; 15 | asm volatile ("mfence"); 16 | return a; 17 | } 18 | 19 | // src: https://github.com/IAIK/flush_flush/blob/master/sc/cacheutils.h 20 | void maccess(void* p) 21 | { 22 | asm volatile ("mov (%0), %%eax\n" 23 | : 24 | : "c" (p) 25 | : "eax"); 26 | } 27 | 28 | // src: https://github.com/IAIK/flush_flush/blob/master/sc/cacheutils.h 29 | void flush(void* p) { 30 | asm volatile ("clflush 0(%0)\n" 31 | : 32 | : "c" (p) 33 | : "rax"); 34 | } 35 | 36 | uint64_t probe(void* p) { 37 | uint64_t start = rdtsc(); 38 | maccess(p); 39 | return rdtsc() - start; 40 | } 41 | 42 | #endif -------------------------------------------------------------------------------- /web/cpuprofiler/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/__init__.py -------------------------------------------------------------------------------- /web/cpuprofiler/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for cpuprofiler project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cpuprofiler.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /web/cpuprofiler/middleware.py: -------------------------------------------------------------------------------- 1 | from django.core.exceptions import MiddlewareNotUsed 2 | from django.http import HttpResponse 3 | from django.conf import settings 4 | import base64 5 | 6 | class SecurityHeadersMiddleware: 7 | def __init__(self, get_response): 8 | self.get_response = get_response 9 | 10 | def __call__(self, request): 11 | response = self.get_response(request) 12 | response["Cross-Origin-Embedder-Policy"] = 'require-corp' 13 | response["Cross-Origin-Opener-Policy"] = 'same-origin' 14 | response["Cross-Origin-Resource-Policy"] = "same-origin" 15 | return response 16 | 17 | # source: https://djangosnippets.org/snippets/2468/ 18 | class BasicAuthMiddleware(object): 19 | 20 | def __init__(self, get_response): 21 | self.AUTH_TEMPLATE = """ Authentication Required Sorry, we're not ready for you yet. """ 22 | self.get_response = get_response 23 | if not settings.DEBUG: 24 | raise MiddlewareNotUsed 25 | 26 | 27 | def _unauthed(self): 28 | response = HttpResponse(self.AUTH_TEMPLATE, content_type="text/html") 29 | response['WWW-Authenticate'] = 'Basic realm="Development"' 30 | response.status_code = 401 31 | return response 32 | 33 | 34 | def __call__(self, request): 35 | if 'HTTP_AUTHORIZATION' not in request.META: 36 | return self._unauthed() 37 | else: 38 | authentication = request.META['HTTP_AUTHORIZATION'] 39 | (auth_method, auth) = authentication.split(' ', 1) 40 | if 'basic' != auth_method.lower(): 41 | return self._unauthed() 42 | auth = base64.b64decode(auth.strip()).decode('utf-8') 43 | username, password = auth.split(':', 1) 44 | if ( 45 | username == settings.BASICAUTH_USERNAME and 46 | password == settings.BASICAUTH_PASSWORD 47 | ): 48 | return self.get_response(request) 49 | 50 | return self._unauthed() -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/css/dashboard.css: -------------------------------------------------------------------------------- 1 | /* DASHBOARD */ 2 | 3 | .dashboard .module table th { 4 | width: 100%; 5 | } 6 | 7 | .dashboard .module table td { 8 | white-space: nowrap; 9 | } 10 | 11 | .dashboard .module table td a { 12 | display: block; 13 | padding-right: .6em; 14 | } 15 | 16 | /* RECENT ACTIONS MODULE */ 17 | 18 | .module ul.actionlist { 19 | margin-left: 0; 20 | } 21 | 22 | ul.actionlist li { 23 | list-style-type: none; 24 | overflow: hidden; 25 | text-overflow: ellipsis; 26 | } 27 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/css/fonts.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Roboto'; 3 | src: url('../fonts/Roboto-Bold-webfont.woff'); 4 | font-weight: 700; 5 | font-style: normal; 6 | } 7 | 8 | @font-face { 9 | font-family: 'Roboto'; 10 | src: url('../fonts/Roboto-Regular-webfont.woff'); 11 | font-weight: 400; 12 | font-style: normal; 13 | } 14 | 15 | @font-face { 16 | font-family: 'Roboto'; 17 | src: url('../fonts/Roboto-Light-webfont.woff'); 18 | font-weight: 300; 19 | font-style: normal; 20 | } 21 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/css/login.css: -------------------------------------------------------------------------------- 1 | /* LOGIN FORM */ 2 | 3 | .login { 4 | background: var(--darkened-bg); 5 | height: auto; 6 | } 7 | 8 | .login #header { 9 | height: auto; 10 | padding: 15px 16px; 11 | justify-content: center; 12 | } 13 | 14 | .login #header h1 { 15 | font-size: 18px; 16 | } 17 | 18 | .login #header h1 a { 19 | color: var(--header-link-color); 20 | } 21 | 22 | .login #content { 23 | padding: 20px 20px 0; 24 | } 25 | 26 | .login #container { 27 | background: var(--body-bg); 28 | border: 1px solid var(--hairline-color); 29 | border-radius: 4px; 30 | overflow: hidden; 31 | width: 28em; 32 | min-width: 300px; 33 | margin: 100px auto; 34 | height: auto; 35 | } 36 | 37 | .login .form-row { 38 | padding: 4px 0; 39 | } 40 | 41 | .login .form-row label { 42 | display: block; 43 | line-height: 2em; 44 | } 45 | 46 | .login .form-row #id_username, .login .form-row #id_password { 47 | padding: 8px; 48 | width: 100%; 49 | box-sizing: border-box; 50 | } 51 | 52 | .login .submit-row { 53 | padding: 1em 0 0 0; 54 | margin: 0; 55 | text-align: center; 56 | } 57 | 58 | .login .password-reset-link { 59 | text-align: center; 60 | } 61 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/css/nav_sidebar.css: -------------------------------------------------------------------------------- 1 | .sticky { 2 | position: sticky; 3 | top: 0; 4 | max-height: 100vh; 5 | } 6 | 7 | .toggle-nav-sidebar { 8 | z-index: 20; 9 | left: 0; 10 | display: flex; 11 | align-items: center; 12 | justify-content: center; 13 | flex: 0 0 23px; 14 | width: 23px; 15 | border: 0; 16 | border-right: 1px solid var(--hairline-color); 17 | background-color: var(--body-bg); 18 | cursor: pointer; 19 | font-size: 20px; 20 | color: var(--link-fg); 21 | padding: 0; 22 | } 23 | 24 | [dir="rtl"] .toggle-nav-sidebar { 25 | border-left: 1px solid var(--hairline-color); 26 | border-right: 0; 27 | } 28 | 29 | .toggle-nav-sidebar:hover, 30 | .toggle-nav-sidebar:focus { 31 | background-color: var(--darkened-bg); 32 | } 33 | 34 | #nav-sidebar { 35 | z-index: 15; 36 | flex: 0 0 275px; 37 | left: -276px; 38 | margin-left: -276px; 39 | border-top: 1px solid transparent; 40 | border-right: 1px solid var(--hairline-color); 41 | background-color: var(--body-bg); 42 | overflow: auto; 43 | } 44 | 45 | [dir="rtl"] #nav-sidebar { 46 | border-left: 1px solid var(--hairline-color); 47 | border-right: 0; 48 | left: 0; 49 | margin-left: 0; 50 | right: -276px; 51 | margin-right: -276px; 52 | } 53 | 54 | .toggle-nav-sidebar::before { 55 | content: '\00BB'; 56 | } 57 | 58 | .main.shifted .toggle-nav-sidebar::before { 59 | content: '\00AB'; 60 | } 61 | 62 | .main.shifted > #nav-sidebar { 63 | left: 24px; 64 | margin-left: 0; 65 | } 66 | 67 | [dir="rtl"] .main.shifted > #nav-sidebar { 68 | left: 0; 69 | right: 24px; 70 | margin-right: 0; 71 | } 72 | 73 | #nav-sidebar .module th { 74 | width: 100%; 75 | overflow-wrap: anywhere; 76 | } 77 | 78 | #nav-sidebar .module th, 79 | #nav-sidebar .module caption { 80 | padding-left: 16px; 81 | } 82 | 83 | #nav-sidebar .module td { 84 | white-space: nowrap; 85 | } 86 | 87 | [dir="rtl"] #nav-sidebar .module th, 88 | [dir="rtl"] #nav-sidebar .module caption { 89 | padding-left: 8px; 90 | padding-right: 16px; 91 | } 92 | 93 | #nav-sidebar .current-app .section:link, 94 | #nav-sidebar .current-app .section:visited { 95 | color: var(--header-color); 96 | font-weight: bold; 97 | } 98 | 99 | #nav-sidebar .current-model { 100 | background: var(--selected-row); 101 | } 102 | 103 | .main > #nav-sidebar + .content { 104 | max-width: calc(100% - 23px); 105 | } 106 | 107 | .main.shifted > #nav-sidebar + .content { 108 | max-width: calc(100% - 299px); 109 | } 110 | 111 | @media (max-width: 767px) { 112 | #nav-sidebar, #toggle-nav-sidebar { 113 | display: none; 114 | } 115 | 116 | .main > #nav-sidebar + .content, 117 | .main.shifted > #nav-sidebar + .content { 118 | max-width: 100%; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/css/responsive_rtl.css: -------------------------------------------------------------------------------- 1 | /* TABLETS */ 2 | 3 | @media (max-width: 1024px) { 4 | [dir="rtl"] .colMS { 5 | margin-right: 0; 6 | } 7 | 8 | [dir="rtl"] #user-tools { 9 | text-align: right; 10 | } 11 | 12 | [dir="rtl"] #changelist .actions label { 13 | padding-left: 10px; 14 | padding-right: 0; 15 | } 16 | 17 | [dir="rtl"] #changelist .actions select { 18 | margin-left: 0; 19 | margin-right: 15px; 20 | } 21 | 22 | [dir="rtl"] .change-list .filtered .results, 23 | [dir="rtl"] .change-list .filtered .paginator, 24 | [dir="rtl"] .filtered #toolbar, 25 | [dir="rtl"] .filtered div.xfull, 26 | [dir="rtl"] .filtered .actions, 27 | [dir="rtl"] #changelist-filter { 28 | margin-left: 0; 29 | } 30 | 31 | [dir="rtl"] .inline-group ul.tools a.add, 32 | [dir="rtl"] .inline-group div.add-row a, 33 | [dir="rtl"] .inline-group .tabular tr.add-row td a { 34 | padding: 8px 26px 8px 10px; 35 | background-position: calc(100% - 8px) 9px; 36 | } 37 | 38 | [dir="rtl"] .related-widget-wrapper-link + .selector { 39 | margin-right: 0; 40 | margin-left: 15px; 41 | } 42 | 43 | [dir="rtl"] .selector .selector-filter label { 44 | margin-right: 0; 45 | margin-left: 8px; 46 | } 47 | 48 | [dir="rtl"] .object-tools li { 49 | float: right; 50 | } 51 | 52 | [dir="rtl"] .object-tools li + li { 53 | margin-left: 0; 54 | margin-right: 15px; 55 | } 56 | 57 | [dir="rtl"] .dashboard .module table td a { 58 | padding-left: 0; 59 | padding-right: 16px; 60 | } 61 | } 62 | 63 | /* MOBILE */ 64 | 65 | @media (max-width: 767px) { 66 | [dir="rtl"] .aligned .related-lookup, 67 | [dir="rtl"] .aligned .datetimeshortcuts { 68 | margin-left: 0; 69 | margin-right: 15px; 70 | } 71 | 72 | [dir="rtl"] .aligned ul { 73 | margin-right: 0; 74 | } 75 | 76 | [dir="rtl"] #changelist-filter { 77 | margin-left: 0; 78 | margin-right: 0; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/css/vendor/select2/LICENSE-SELECT2.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Roboto webfont source: https://www.google.com/fonts/specimen/Roboto 2 | WOFF files extracted using https://github.com/majodev/google-webfonts-helper 3 | Weights used in this project: Light (300), Regular (400), Bold (700) 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/fonts/Roboto-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/admin/fonts/Roboto-Bold-webfont.woff -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/fonts/Roboto-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/admin/fonts/Roboto-Light-webfont.woff -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/fonts/Roboto-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/admin/fonts/Roboto-Regular-webfont.woff -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Code Charm Ltd 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/README.txt: -------------------------------------------------------------------------------- 1 | All icons are taken from Font Awesome (http://fontawesome.io/) project. 2 | The Font Awesome font is licensed under the SIL OFL 1.1: 3 | - https://scripts.sil.org/OFL 4 | 5 | SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG 6 | Font-Awesome-SVG-PNG is licensed under the MIT license (see file license 7 | in current folder). 8 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/calendar-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/gis/move_vertex_off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/gis/move_vertex_on.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-addlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-alert.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-calendar.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-changelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-clock.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-deletelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-no.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-unknown-alt.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-unknown.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-viewlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/inline-delete.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/sorting-icons.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/tooltag-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/img/tooltag-arrowright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/autocomplete.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | const $ = django.jQuery; 4 | const init = function($element, options) { 5 | const settings = $.extend({ 6 | ajax: { 7 | data: function(params) { 8 | return { 9 | term: params.term, 10 | page: params.page, 11 | app_label: $element.data('app-label'), 12 | model_name: $element.data('model-name'), 13 | field_name: $element.data('field-name') 14 | }; 15 | } 16 | } 17 | }, options); 18 | $element.select2(settings); 19 | }; 20 | 21 | $.fn.djangoAdminSelect2 = function(options) { 22 | const settings = $.extend({}, options); 23 | $.each(this, function(i, element) { 24 | const $element = $(element); 25 | init($element, settings); 26 | }); 27 | return this; 28 | }; 29 | 30 | $(function() { 31 | // Initialize all autocomplete widgets except the one in the template 32 | // form used when a new formset is added. 33 | $('.admin-autocomplete').not('[name*=__prefix__]').djangoAdminSelect2(); 34 | }); 35 | 36 | $(document).on('formset:added', (function() { 37 | return function(event, $newFormset) { 38 | return $newFormset.find('.admin-autocomplete').djangoAdminSelect2(); 39 | }; 40 | })(this)); 41 | } 42 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/cancel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | // Call function fn when the DOM is loaded and ready. If it is already 4 | // loaded, call the function now. 5 | // http://youmightnotneedjquery.com/#ready 6 | function ready(fn) { 7 | if (document.readyState !== 'loading') { 8 | fn(); 9 | } else { 10 | document.addEventListener('DOMContentLoaded', fn); 11 | } 12 | } 13 | 14 | ready(function() { 15 | function handleClick(event) { 16 | event.preventDefault(); 17 | const params = new URLSearchParams(window.location.search); 18 | if (params.has('_popup')) { 19 | window.close(); // Close the popup. 20 | } else { 21 | window.history.back(); // Otherwise, go back. 22 | } 23 | } 24 | 25 | document.querySelectorAll('.cancel-link').forEach(function(el) { 26 | el.addEventListener('click', handleClick); 27 | }); 28 | }); 29 | } 30 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/change_form.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | const inputTags = ['BUTTON', 'INPUT', 'SELECT', 'TEXTAREA']; 4 | const modelName = document.getElementById('django-admin-form-add-constants').dataset.modelName; 5 | if (modelName) { 6 | const form = document.getElementById(modelName + '_form'); 7 | for (const element of form.elements) { 8 | // HTMLElement.offsetParent returns null when the element is not 9 | // rendered. 10 | if (inputTags.includes(element.tagName) && !element.disabled && element.offsetParent) { 11 | element.focus(); 12 | break; 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/collapse.js: -------------------------------------------------------------------------------- 1 | /*global gettext*/ 2 | 'use strict'; 3 | { 4 | window.addEventListener('load', function() { 5 | // Add anchor tag for Show/Hide link 6 | const fieldsets = document.querySelectorAll('fieldset.collapse'); 7 | for (const [i, elem] of fieldsets.entries()) { 8 | // Don't hide if fields in this fieldset have errors 9 | if (elem.querySelectorAll('div.errors, ul.errorlist').length === 0) { 10 | elem.classList.add('collapsed'); 11 | const h2 = elem.querySelector('h2'); 12 | const link = document.createElement('a'); 13 | link.id = 'fieldsetcollapser' + i; 14 | link.className = 'collapse-toggle'; 15 | link.href = '#'; 16 | link.textContent = gettext('Show'); 17 | h2.appendChild(document.createTextNode(' (')); 18 | h2.appendChild(link); 19 | h2.appendChild(document.createTextNode(')')); 20 | } 21 | } 22 | // Add toggle to hide/show anchor tag 23 | const toggleFunc = function(ev) { 24 | if (ev.target.matches('.collapse-toggle')) { 25 | ev.preventDefault(); 26 | ev.stopPropagation(); 27 | const fieldset = ev.target.closest('fieldset'); 28 | if (fieldset.classList.contains('collapsed')) { 29 | // Show 30 | ev.target.textContent = gettext('Hide'); 31 | fieldset.classList.remove('collapsed'); 32 | } else { 33 | // Hide 34 | ev.target.textContent = gettext('Show'); 35 | fieldset.classList.add('collapsed'); 36 | } 37 | } 38 | }; 39 | document.querySelectorAll('fieldset.module').forEach(function(el) { 40 | el.addEventListener('click', toggleFunc); 41 | }); 42 | }); 43 | } 44 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/jquery.init.js: -------------------------------------------------------------------------------- 1 | /*global jQuery:false*/ 2 | 'use strict'; 3 | /* Puts the included jQuery into our own namespace using noConflict and passing 4 | * it 'true'. This ensures that the included jQuery doesn't pollute the global 5 | * namespace (i.e. this preserves pre-existing values for both window.$ and 6 | * window.jQuery). 7 | */ 8 | window.django = {jQuery: jQuery.noConflict(true)}; 9 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/nav_sidebar.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | const toggleNavSidebar = document.getElementById('toggle-nav-sidebar'); 4 | if (toggleNavSidebar !== null) { 5 | const navLinks = document.querySelectorAll('#nav-sidebar a'); 6 | function disableNavLinkTabbing() { 7 | for (const navLink of navLinks) { 8 | navLink.tabIndex = -1; 9 | } 10 | } 11 | function enableNavLinkTabbing() { 12 | for (const navLink of navLinks) { 13 | navLink.tabIndex = 0; 14 | } 15 | } 16 | 17 | const main = document.getElementById('main'); 18 | let navSidebarIsOpen = localStorage.getItem('django.admin.navSidebarIsOpen'); 19 | if (navSidebarIsOpen === null) { 20 | navSidebarIsOpen = 'true'; 21 | } 22 | if (navSidebarIsOpen === 'false') { 23 | disableNavLinkTabbing(); 24 | } 25 | main.classList.toggle('shifted', navSidebarIsOpen === 'true'); 26 | 27 | toggleNavSidebar.addEventListener('click', function() { 28 | if (navSidebarIsOpen === 'true') { 29 | navSidebarIsOpen = 'false'; 30 | disableNavLinkTabbing(); 31 | } else { 32 | navSidebarIsOpen = 'true'; 33 | enableNavLinkTabbing(); 34 | } 35 | localStorage.setItem('django.admin.navSidebarIsOpen', navSidebarIsOpen); 36 | main.classList.toggle('shifted'); 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/popup_response.js: -------------------------------------------------------------------------------- 1 | /*global opener */ 2 | 'use strict'; 3 | { 4 | const initData = JSON.parse(document.getElementById('django-admin-popup-response-constants').dataset.popupResponse); 5 | switch(initData.action) { 6 | case 'change': 7 | opener.dismissChangeRelatedObjectPopup(window, initData.value, initData.obj, initData.new_value); 8 | break; 9 | case 'delete': 10 | opener.dismissDeleteRelatedObjectPopup(window, initData.value); 11 | break; 12 | default: 13 | opener.dismissAddRelatedObjectPopup(window, initData.value, initData.obj); 14 | break; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/prepopulate.js: -------------------------------------------------------------------------------- 1 | /*global URLify*/ 2 | 'use strict'; 3 | { 4 | const $ = django.jQuery; 5 | $.fn.prepopulate = function(dependencies, maxLength, allowUnicode) { 6 | /* 7 | Depends on urlify.js 8 | Populates a selected field with the values of the dependent fields, 9 | URLifies and shortens the string. 10 | dependencies - array of dependent fields ids 11 | maxLength - maximum length of the URLify'd string 12 | allowUnicode - Unicode support of the URLify'd string 13 | */ 14 | return this.each(function() { 15 | const prepopulatedField = $(this); 16 | 17 | const populate = function() { 18 | // Bail if the field's value has been changed by the user 19 | if (prepopulatedField.data('_changed')) { 20 | return; 21 | } 22 | 23 | const values = []; 24 | $.each(dependencies, function(i, field) { 25 | field = $(field); 26 | if (field.val().length > 0) { 27 | values.push(field.val()); 28 | } 29 | }); 30 | prepopulatedField.val(URLify(values.join(' '), maxLength, allowUnicode)); 31 | }; 32 | 33 | prepopulatedField.data('_changed', false); 34 | prepopulatedField.on('change', function() { 35 | prepopulatedField.data('_changed', true); 36 | }); 37 | 38 | if (!prepopulatedField.val()) { 39 | $(dependencies.join(',')).on('keyup change focus', populate); 40 | } 41 | }); 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/prepopulate_init.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | { 3 | const $ = django.jQuery; 4 | const fields = $('#django-admin-prepopulated-fields-constants').data('prepopulatedFields'); 5 | $.each(fields, function(index, field) { 6 | $('.empty-form .form-row .field-' + field.name + ', .empty-form.form-row .field-' + field.name).addClass('prepopulated_field'); 7 | $(field.id).data('dependency_list', field.dependency_list).prepopulate( 8 | field.dependency_ids, field.maxLength, field.allowUnicode 9 | ); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2012-2017 Kevin Brown, Igor Vaynberg, and Select2 contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/af.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/af",[],function(){return{errorLoading:function(){return"Die resultate kon nie gelaai word nie."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Verwyders asseblief "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Voer asseblief "+(e.minimum-e.input.length)+" of meer karakters"},loadingMore:function(){return"Meer resultate word gelaai…"},maximumSelected:function(e){var n="Kies asseblief net "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"Geen resultate gevind"},searching:function(){return"Besig…"},removeAllItems:function(){return"Verwyder alle items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ar.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ar",[],function(){return{errorLoading:function(){return"لا يمكن تحميل النتائج"},inputTooLong:function(n){return"الرجاء حذف "+(n.input.length-n.maximum)+" عناصر"},inputTooShort:function(n){return"الرجاء إضافة "+(n.minimum-n.input.length)+" عناصر"},loadingMore:function(){return"جاري تحميل نتائج إضافية..."},maximumSelected:function(n){return"تستطيع إختيار "+n.maximum+" بنود فقط"},noResults:function(){return"لم يتم العثور على أي نتائج"},searching:function(){return"جاري البحث…"},removeAllItems:function(){return"قم بإزالة كل العناصر"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/az.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/az",[],function(){return{inputTooLong:function(n){return n.input.length-n.maximum+" simvol silin"},inputTooShort:function(n){return n.minimum-n.input.length+" simvol daxil edin"},loadingMore:function(){return"Daha çox nəticə yüklənir…"},maximumSelected:function(n){return"Sadəcə "+n.maximum+" element seçə bilərsiniz"},noResults:function(){return"Nəticə tapılmadı"},searching:function(){return"Axtarılır…"},removeAllItems:function(){return"Bütün elementləri sil"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/bg.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bg",[],function(){return{inputTooLong:function(n){var e=n.input.length-n.maximum,u="Моля въведете с "+e+" по-малко символ";return e>1&&(u+="a"),u},inputTooShort:function(n){var e=n.minimum-n.input.length,u="Моля въведете още "+e+" символ";return e>1&&(u+="a"),u},loadingMore:function(){return"Зареждат се още…"},maximumSelected:function(n){var e="Можете да направите до "+n.maximum+" ";return n.maximum>1?e+="избора":e+="избор",e},noResults:function(){return"Няма намерени съвпадения"},searching:function(){return"Търсене…"},removeAllItems:function(){return"Премахнете всички елементи"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/bn.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/bn",[],function(){return{errorLoading:function(){return"ফলাফলগুলি লোড করা যায়নি।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।";return 1!=e&&(u="অনুগ্রহ করে "+e+" টি অক্ষর মুছে দিন।"),u},inputTooShort:function(n){return n.minimum-n.input.length+" টি অক্ষর অথবা অধিক অক্ষর লিখুন।"},loadingMore:function(){return"আরো ফলাফল লোড হচ্ছে ..."},maximumSelected:function(n){var e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।";return 1!=n.maximum&&(e=n.maximum+" টি আইটেম নির্বাচন করতে পারবেন।"),e},noResults:function(){return"কোন ফলাফল পাওয়া যায়নি।"},searching:function(){return"অনুসন্ধান করা হচ্ছে ..."}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/bs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/bs",[],function(){function e(e,n,r,t){return e%10==1&&e%100!=11?n:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspijelo."},inputTooLong:function(n){var r=n.input.length-n.maximum,t="Obrišite "+r+" simbol";return t+=e(r,"","a","a")},inputTooShort:function(n){var r=n.minimum-n.input.length,t="Ukucajte bar još "+r+" simbol";return t+=e(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(n){var r="Možete izabrati samo "+n.maximum+" stavk";return r+=e(n.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Uklonite sve stavke"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ca.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ca",[],function(){return{errorLoading:function(){return"La càrrega ha fallat"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Si us plau, elimina "+n+" car";return r+=1==n?"àcter":"àcters"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Si us plau, introdueix "+n+" car";return r+=1==n?"àcter":"àcters"},loadingMore:function(){return"Carregant més resultats…"},maximumSelected:function(e){var n="Només es pot seleccionar "+e.maximum+" element";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No s'han trobat resultats"},searching:function(){return"Cercant…"},removeAllItems:function(){return"Treu tots els elements"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/cs.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/cs",[],function(){function e(e,n){switch(e){case 2:return n?"dva":"dvě";case 3:return"tři";case 4:return"čtyři"}return""}return{errorLoading:function(){return"Výsledky nemohly být načteny."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadejte o jeden znak méně.":t<=4?"Prosím, zadejte o "+e(t,!0)+" znaky méně.":"Prosím, zadejte o "+t+" znaků méně."},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadejte ještě jeden znak.":t<=4?"Prosím, zadejte ještě další "+e(t,!0)+" znaky.":"Prosím, zadejte ještě dalších "+t+" znaků."},loadingMore:function(){return"Načítají se další výsledky…"},maximumSelected:function(n){var t=n.maximum;return 1==t?"Můžete zvolit jen jednu položku.":t<=4?"Můžete zvolit maximálně "+e(t,!1)+" položky.":"Můžete zvolit maximálně "+t+" položek."},noResults:function(){return"Nenalezeny žádné položky."},searching:function(){return"Vyhledávání…"},removeAllItems:function(){return"Odstraňte všechny položky"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/da.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/da",[],function(){return{errorLoading:function(){return"Resultaterne kunne ikke indlæses."},inputTooLong:function(e){return"Angiv venligst "+(e.input.length-e.maximum)+" tegn mindre"},inputTooShort:function(e){return"Angiv venligst "+(e.minimum-e.input.length)+" tegn mere"},loadingMore:function(){return"Indlæser flere resultater…"},maximumSelected:function(e){var n="Du kan kun vælge "+e.maximum+" emne";return 1!=e.maximum&&(n+="r"),n},noResults:function(){return"Ingen resultater fundet"},searching:function(){return"Søger…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/de.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/de",[],function(){return{errorLoading:function(){return"Die Ergebnisse konnten nicht geladen werden."},inputTooLong:function(e){return"Bitte "+(e.input.length-e.maximum)+" Zeichen weniger eingeben"},inputTooShort:function(e){return"Bitte "+(e.minimum-e.input.length)+" Zeichen mehr eingeben"},loadingMore:function(){return"Lade mehr Ergebnisse…"},maximumSelected:function(e){var n="Sie können nur "+e.maximum+" Element";return 1!=e.maximum&&(n+="e"),n+=" auswählen"},noResults:function(){return"Keine Übereinstimmungen gefunden"},searching:function(){return"Suche…"},removeAllItems:function(){return"Entferne alle Elemente"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/dsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/dsb",[],function(){var n=["znamuško","znamušce","znamuška","znamuškow"],e=["zapisk","zapiska","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njejsu se dali zacytaś."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Pšosym lašuj "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Pšosym zapódaj nanejmjenjej "+a+" "+u(a,n)},loadingMore:function(){return"Dalšne wuslědki se zacytaju…"},maximumSelected:function(n){return"Móžoš jano "+n.maximum+" "+u(n.maximum,e)+"wubraś."},noResults:function(){return"Žedne wuslědki namakane"},searching:function(){return"Pyta se…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/el.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/el",[],function(){return{errorLoading:function(){return"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν."},inputTooLong:function(n){var e=n.input.length-n.maximum,u="Παρακαλώ διαγράψτε "+e+" χαρακτήρ";return 1==e&&(u+="α"),1!=e&&(u+="ες"),u},inputTooShort:function(n){return"Παρακαλώ συμπληρώστε "+(n.minimum-n.input.length)+" ή περισσότερους χαρακτήρες"},loadingMore:function(){return"Φόρτωση περισσότερων αποτελεσμάτων…"},maximumSelected:function(n){var e="Μπορείτε να επιλέξετε μόνο "+n.maximum+" επιλογ";return 1==n.maximum&&(e+="ή"),1!=n.maximum&&(e+="ές"),e},noResults:function(){return"Δεν βρέθηκαν αποτελέσματα"},searching:function(){return"Αναζήτηση…"},removeAllItems:function(){return"Καταργήστε όλα τα στοιχεία"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/en.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/en",[],function(){return{errorLoading:function(){return"The results could not be loaded."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Please delete "+n+" character";return 1!=n&&(r+="s"),r},inputTooShort:function(e){return"Please enter "+(e.minimum-e.input.length)+" or more characters"},loadingMore:function(){return"Loading more results…"},maximumSelected:function(e){var n="You can only select "+e.maximum+" item";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No results found"},searching:function(){return"Searching…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/es.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/es",[],function(){return{errorLoading:function(){return"No se pudieron cargar los resultados"},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Por favor, elimine "+n+" car";return r+=1==n?"ácter":"acteres"},inputTooShort:function(e){var n=e.minimum-e.input.length,r="Por favor, introduzca "+n+" car";return r+=1==n?"ácter":"acteres"},loadingMore:function(){return"Cargando más resultados…"},maximumSelected:function(e){var n="Sólo puede seleccionar "+e.maximum+" elemento";return 1!=e.maximum&&(n+="s"),n},noResults:function(){return"No se encontraron resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Eliminar todos los elementos"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/et.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/et",[],function(){return{inputTooLong:function(e){var n=e.input.length-e.maximum,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" vähem"},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Sisesta "+n+" täht";return 1!=n&&(t+="e"),t+=" rohkem"},loadingMore:function(){return"Laen tulemusi…"},maximumSelected:function(e){var n="Saad vaid "+e.maximum+" tulemus";return 1==e.maximum?n+="e":n+="t",n+=" valida"},noResults:function(){return"Tulemused puuduvad"},searching:function(){return"Otsin…"},removeAllItems:function(){return"Eemalda kõik esemed"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/eu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/eu",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gutxiago"},inputTooShort:function(e){var t=e.minimum-e.input.length,n="Idatzi ";return n+=1==t?"karaktere bat":t+" karaktere",n+=" gehiago"},loadingMore:function(){return"Emaitza gehiago kargatzen…"},maximumSelected:function(e){return 1===e.maximum?"Elementu bakarra hauta dezakezu":e.maximum+" elementu hauta ditzakezu soilik"},noResults:function(){return"Ez da bat datorrenik aurkitu"},searching:function(){return"Bilatzen…"},removeAllItems:function(){return"Kendu elementu guztiak"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/fa.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fa",[],function(){return{errorLoading:function(){return"امکان بارگذاری نتایج وجود ندارد."},inputTooLong:function(n){return"لطفاً "+(n.input.length-n.maximum)+" کاراکتر را حذف نمایید"},inputTooShort:function(n){return"لطفاً تعداد "+(n.minimum-n.input.length)+" کاراکتر یا بیشتر وارد نمایید"},loadingMore:function(){return"در حال بارگذاری نتایج بیشتر..."},maximumSelected:function(n){return"شما تنها می‌توانید "+n.maximum+" آیتم را انتخاب نمایید"},noResults:function(){return"هیچ نتیجه‌ای یافت نشد"},searching:function(){return"در حال جستجو..."},removeAllItems:function(){return"همه موارد را حذف کنید"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/fi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/fi",[],function(){return{errorLoading:function(){return"Tuloksia ei saatu ladattua."},inputTooLong:function(n){return"Ole hyvä ja anna "+(n.input.length-n.maximum)+" merkkiä vähemmän"},inputTooShort:function(n){return"Ole hyvä ja anna "+(n.minimum-n.input.length)+" merkkiä lisää"},loadingMore:function(){return"Ladataan lisää tuloksia…"},maximumSelected:function(n){return"Voit valita ainoastaan "+n.maximum+" kpl"},noResults:function(){return"Ei tuloksia"},searching:function(){return"Haetaan…"},removeAllItems:function(){return"Poista kaikki kohteet"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/fr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/fr",[],function(){return{errorLoading:function(){return"Les résultats ne peuvent pas être chargés."},inputTooLong:function(e){var n=e.input.length-e.maximum;return"Supprimez "+n+" caractère"+(n>1?"s":"")},inputTooShort:function(e){var n=e.minimum-e.input.length;return"Saisissez au moins "+n+" caractère"+(n>1?"s":"")},loadingMore:function(){return"Chargement de résultats supplémentaires…"},maximumSelected:function(e){return"Vous pouvez seulement sélectionner "+e.maximum+" élément"+(e.maximum>1?"s":"")},noResults:function(){return"Aucun résultat trouvé"},searching:function(){return"Recherche en cours…"},removeAllItems:function(){return"Supprimer tous les éléments"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/gl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/gl",[],function(){return{errorLoading:function(){return"Non foi posíbel cargar os resultados."},inputTooLong:function(e){var n=e.input.length-e.maximum;return 1===n?"Elimine un carácter":"Elimine "+n+" caracteres"},inputTooShort:function(e){var n=e.minimum-e.input.length;return 1===n?"Engada un carácter":"Engada "+n+" caracteres"},loadingMore:function(){return"Cargando máis resultados…"},maximumSelected:function(e){return 1===e.maximum?"Só pode seleccionar un elemento":"Só pode seleccionar "+e.maximum+" elementos"},noResults:function(){return"Non se atoparon resultados"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Elimina todos os elementos"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/he.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/he",[],function(){return{errorLoading:function(){return"שגיאה בטעינת התוצאות"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="נא למחוק ";return r+=1===e?"תו אחד":e+" תווים"},inputTooShort:function(n){var e=n.minimum-n.input.length,r="נא להכניס ";return r+=1===e?"תו אחד":e+" תווים",r+=" או יותר"},loadingMore:function(){return"טוען תוצאות נוספות…"},maximumSelected:function(n){var e="באפשרותך לבחור עד ";return 1===n.maximum?e+="פריט אחד":e+=n.maximum+" פריטים",e},noResults:function(){return"לא נמצאו תוצאות"},searching:function(){return"מחפש…"},removeAllItems:function(){return"הסר את כל הפריטים"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/hi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hi",[],function(){return{errorLoading:function(){return"परिणामों को लोड नहीं किया जा सका।"},inputTooLong:function(n){var e=n.input.length-n.maximum,r=e+" अक्षर को हटा दें";return e>1&&(r=e+" अक्षरों को हटा दें "),r},inputTooShort:function(n){return"कृपया "+(n.minimum-n.input.length)+" या अधिक अक्षर दर्ज करें"},loadingMore:function(){return"अधिक परिणाम लोड हो रहे है..."},maximumSelected:function(n){return"आप केवल "+n.maximum+" आइटम का चयन कर सकते हैं"},noResults:function(){return"कोई परिणाम नहीं मिला"},searching:function(){return"खोज रहा है..."},removeAllItems:function(){return"सभी वस्तुओं को हटा दें"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/hr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hr",[],function(){function n(n){var e=" "+n+" znak";return n%10<5&&n%10>0&&(n%100<5||n%100>19)?n%10>1&&(e+="a"):e+="ova",e}return{errorLoading:function(){return"Preuzimanje nije uspjelo."},inputTooLong:function(e){return"Unesite "+n(e.input.length-e.maximum)},inputTooShort:function(e){return"Unesite još "+n(e.minimum-e.input.length)},loadingMore:function(){return"Učitavanje rezultata…"},maximumSelected:function(n){return"Maksimalan broj odabranih stavki je "+n.maximum},noResults:function(){return"Nema rezultata"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Ukloni sve stavke"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/hsb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hsb",[],function(){var n=["znamješko","znamješce","znamješka","znamješkow"],e=["zapisk","zapiskaj","zapiski","zapiskow"],u=function(n,e){return 1===n?e[0]:2===n?e[1]:n>2&&n<=4?e[2]:n>=5?e[3]:void 0};return{errorLoading:function(){return"Wuslědki njedachu so začitać."},inputTooLong:function(e){var a=e.input.length-e.maximum;return"Prošu zhašej "+a+" "+u(a,n)},inputTooShort:function(e){var a=e.minimum-e.input.length;return"Prošu zapodaj znajmjeńša "+a+" "+u(a,n)},loadingMore:function(){return"Dalše wuslědki so začitaja…"},maximumSelected:function(n){return"Móžeš jenož "+n.maximum+" "+u(n.maximum,e)+"wubrać"},noResults:function(){return"Žane wuslědki namakane"},searching:function(){return"Pyta so…"},removeAllItems:function(){return"Remove all items"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/hu.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/hu",[],function(){return{errorLoading:function(){return"Az eredmények betöltése nem sikerült."},inputTooLong:function(e){return"Túl hosszú. "+(e.input.length-e.maximum)+" karakterrel több, mint kellene."},inputTooShort:function(e){return"Túl rövid. Még "+(e.minimum-e.input.length)+" karakter hiányzik."},loadingMore:function(){return"Töltés…"},maximumSelected:function(e){return"Csak "+e.maximum+" elemet lehet kiválasztani."},noResults:function(){return"Nincs találat."},searching:function(){return"Keresés…"},removeAllItems:function(){return"Távolítson el minden elemet"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/hy.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/hy",[],function(){return{errorLoading:function(){return"Արդյունքները հնարավոր չէ բեռնել։"},inputTooLong:function(n){return"Խնդրում ենք հեռացնել "+(n.input.length-n.maximum)+" նշան"},inputTooShort:function(n){return"Խնդրում ենք մուտքագրել "+(n.minimum-n.input.length)+" կամ ավել նշաններ"},loadingMore:function(){return"Բեռնվում են նոր արդյունքներ․․․"},maximumSelected:function(n){return"Դուք կարող եք ընտրել առավելագույնը "+n.maximum+" կետ"},noResults:function(){return"Արդյունքներ չեն գտնվել"},searching:function(){return"Որոնում․․․"},removeAllItems:function(){return"Հեռացնել բոլոր տարրերը"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/id.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/id",[],function(){return{errorLoading:function(){return"Data tidak boleh diambil."},inputTooLong:function(n){return"Hapuskan "+(n.input.length-n.maximum)+" huruf"},inputTooShort:function(n){return"Masukkan "+(n.minimum-n.input.length)+" huruf lagi"},loadingMore:function(){return"Mengambil data…"},maximumSelected:function(n){return"Anda hanya dapat memilih "+n.maximum+" pilihan"},noResults:function(){return"Tidak ada data yang sesuai"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Hapus semua item"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/is.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/is",[],function(){return{inputTooLong:function(n){var t=n.input.length-n.maximum,e="Vinsamlegast styttið texta um "+t+" staf";return t<=1?e:e+"i"},inputTooShort:function(n){var t=n.minimum-n.input.length,e="Vinsamlegast skrifið "+t+" staf";return t>1&&(e+="i"),e+=" í viðbót"},loadingMore:function(){return"Sæki fleiri niðurstöður…"},maximumSelected:function(n){return"Þú getur aðeins valið "+n.maximum+" atriði"},noResults:function(){return"Ekkert fannst"},searching:function(){return"Leita…"},removeAllItems:function(){return"Fjarlægðu öll atriði"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/it.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/it",[],function(){return{errorLoading:function(){return"I risultati non possono essere caricati."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Per favore cancella "+n+" caratter";return t+=1!==n?"i":"e"},inputTooShort:function(e){return"Per favore inserisci "+(e.minimum-e.input.length)+" o più caratteri"},loadingMore:function(){return"Caricando più risultati…"},maximumSelected:function(e){var n="Puoi selezionare solo "+e.maximum+" element";return 1!==e.maximum?n+="i":n+="o",n},noResults:function(){return"Nessun risultato trovato"},searching:function(){return"Sto cercando…"},removeAllItems:function(){return"Rimuovi tutti gli oggetti"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ja.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ja",[],function(){return{errorLoading:function(){return"結果が読み込まれませんでした"},inputTooLong:function(n){return n.input.length-n.maximum+" 文字を削除してください"},inputTooShort:function(n){return"少なくとも "+(n.minimum-n.input.length)+" 文字を入力してください"},loadingMore:function(){return"読み込み中…"},maximumSelected:function(n){return n.maximum+" 件しか選択できません"},noResults:function(){return"対象が見つかりません"},searching:function(){return"検索しています…"},removeAllItems:function(){return"すべてのアイテムを削除"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ka.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ka",[],function(){return{errorLoading:function(){return"მონაცემების ჩატვირთვა შეუძლებელია."},inputTooLong:function(n){return"გთხოვთ აკრიფეთ "+(n.input.length-n.maximum)+" სიმბოლოთი ნაკლები"},inputTooShort:function(n){return"გთხოვთ აკრიფეთ "+(n.minimum-n.input.length)+" სიმბოლო ან მეტი"},loadingMore:function(){return"მონაცემების ჩატვირთვა…"},maximumSelected:function(n){return"თქვენ შეგიძლიათ აირჩიოთ არაუმეტეს "+n.maximum+" ელემენტი"},noResults:function(){return"რეზულტატი არ მოიძებნა"},searching:function(){return"ძიება…"},removeAllItems:function(){return"ამოიღე ყველა ელემენტი"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/km.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/km",[],function(){return{errorLoading:function(){return"មិនអាចទាញយកទិន្នន័យ"},inputTooLong:function(n){return"សូមលុបចេញ "+(n.input.length-n.maximum)+" អក្សរ"},inputTooShort:function(n){return"សូមបញ្ចូល"+(n.minimum-n.input.length)+" អក្សរ រឺ ច្រើនជាងនេះ"},loadingMore:function(){return"កំពុងទាញយកទិន្នន័យបន្ថែម..."},maximumSelected:function(n){return"អ្នកអាចជ្រើសរើសបានតែ "+n.maximum+" ជម្រើសប៉ុណ្ណោះ"},noResults:function(){return"មិនមានលទ្ធផល"},searching:function(){return"កំពុងស្វែងរក..."},removeAllItems:function(){return"លុបធាតុទាំងអស់"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ko.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ko",[],function(){return{errorLoading:function(){return"결과를 불러올 수 없습니다."},inputTooLong:function(n){return"너무 깁니다. "+(n.input.length-n.maximum)+" 글자 지워주세요."},inputTooShort:function(n){return"너무 짧습니다. "+(n.minimum-n.input.length)+" 글자 더 입력해주세요."},loadingMore:function(){return"불러오는 중…"},maximumSelected:function(n){return"최대 "+n.maximum+"개까지만 선택 가능합니다."},noResults:function(){return"결과가 없습니다."},searching:function(){return"검색 중…"},removeAllItems:function(){return"모든 항목 삭제"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/lt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/lt",[],function(){function n(n,e,i,t){return n%10==1&&(n%100<11||n%100>19)?e:n%10>=2&&n%10<=9&&(n%100<11||n%100>19)?i:t}return{inputTooLong:function(e){var i=e.input.length-e.maximum,t="Pašalinkite "+i+" simbol";return t+=n(i,"į","ius","ių")},inputTooShort:function(e){var i=e.minimum-e.input.length,t="Įrašykite dar "+i+" simbol";return t+=n(i,"į","ius","ių")},loadingMore:function(){return"Kraunama daugiau rezultatų…"},maximumSelected:function(e){var i="Jūs galite pasirinkti tik "+e.maximum+" element";return i+=n(e.maximum,"ą","us","ų")},noResults:function(){return"Atitikmenų nerasta"},searching:function(){return"Ieškoma…"},removeAllItems:function(){return"Pašalinti visus elementus"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/lv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/lv",[],function(){function e(e,n,u,i){return 11===e?n:e%10==1?u:i}return{inputTooLong:function(n){var u=n.input.length-n.maximum,i="Lūdzu ievadiet par "+u;return(i+=" simbol"+e(u,"iem","u","iem"))+" mazāk"},inputTooShort:function(n){var u=n.minimum-n.input.length,i="Lūdzu ievadiet vēl "+u;return i+=" simbol"+e(u,"us","u","us")},loadingMore:function(){return"Datu ielāde…"},maximumSelected:function(n){var u="Jūs varat izvēlēties ne vairāk kā "+n.maximum;return u+=" element"+e(n.maximum,"us","u","us")},noResults:function(){return"Sakritību nav"},searching:function(){return"Meklēšana…"},removeAllItems:function(){return"Noņemt visus vienumus"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/mk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/mk",[],function(){return{inputTooLong:function(n){var e=(n.input.length,n.maximum,"Ве молиме внесете "+n.maximum+" помалку карактер");return 1!==n.maximum&&(e+="и"),e},inputTooShort:function(n){var e=(n.minimum,n.input.length,"Ве молиме внесете уште "+n.maximum+" карактер");return 1!==n.maximum&&(e+="и"),e},loadingMore:function(){return"Вчитување резултати…"},maximumSelected:function(n){var e="Можете да изберете само "+n.maximum+" ставк";return 1===n.maximum?e+="а":e+="и",e},noResults:function(){return"Нема пронајдено совпаѓања"},searching:function(){return"Пребарување…"},removeAllItems:function(){return"Отстрани ги сите предмети"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ms.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ms",[],function(){return{errorLoading:function(){return"Keputusan tidak berjaya dimuatkan."},inputTooLong:function(n){return"Sila hapuskan "+(n.input.length-n.maximum)+" aksara"},inputTooShort:function(n){return"Sila masukkan "+(n.minimum-n.input.length)+" atau lebih aksara"},loadingMore:function(){return"Sedang memuatkan keputusan…"},maximumSelected:function(n){return"Anda hanya boleh memilih "+n.maximum+" pilihan"},noResults:function(){return"Tiada padanan yang ditemui"},searching:function(){return"Mencari…"},removeAllItems:function(){return"Keluarkan semua item"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/nb.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nb",[],function(){return{errorLoading:function(){return"Kunne ikke hente resultater."},inputTooLong:function(e){return"Vennligst fjern "+(e.input.length-e.maximum)+" tegn"},inputTooShort:function(e){return"Vennligst skriv inn "+(e.minimum-e.input.length)+" tegn til"},loadingMore:function(){return"Laster flere resultater…"},maximumSelected:function(e){return"Du kan velge maks "+e.maximum+" elementer"},noResults:function(){return"Ingen treff"},searching:function(){return"Søker…"},removeAllItems:function(){return"Fjern alle elementer"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ne.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ne",[],function(){return{errorLoading:function(){return"नतिजाहरु देखाउन सकिएन।"},inputTooLong:function(n){var e=n.input.length-n.maximum,u="कृपया "+e+" अक्षर मेटाउनुहोस्।";return 1!=e&&(u+="कृपया "+e+" अक्षरहरु मेटाउनुहोस्।"),u},inputTooShort:function(n){return"कृपया बाँकी रहेका "+(n.minimum-n.input.length)+" वा अरु धेरै अक्षरहरु भर्नुहोस्।"},loadingMore:function(){return"अरु नतिजाहरु भरिँदैछन् …"},maximumSelected:function(n){var e="तँपाई "+n.maximum+" वस्तु मात्र छान्न पाउँनुहुन्छ।";return 1!=n.maximum&&(e="तँपाई "+n.maximum+" वस्तुहरु मात्र छान्न पाउँनुहुन्छ।"),e},noResults:function(){return"कुनै पनि नतिजा भेटिएन।"},searching:function(){return"खोजि हुँदैछ…"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/nl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/nl",[],function(){return{errorLoading:function(){return"De resultaten konden niet worden geladen."},inputTooLong:function(e){return"Gelieve "+(e.input.length-e.maximum)+" karakters te verwijderen"},inputTooShort:function(e){return"Gelieve "+(e.minimum-e.input.length)+" of meer karakters in te voeren"},loadingMore:function(){return"Meer resultaten laden…"},maximumSelected:function(e){var n=1==e.maximum?"kan":"kunnen",r="Er "+n+" maar "+e.maximum+" item";return 1!=e.maximum&&(r+="s"),r+=" worden geselecteerd"},noResults:function(){return"Geen resultaten gevonden…"},searching:function(){return"Zoeken…"},removeAllItems:function(){return"Verwijder alle items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/pl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/pl",[],function(){var n=["znak","znaki","znaków"],e=["element","elementy","elementów"],r=function(n,e){return 1===n?e[0]:n>1&&n<=4?e[1]:n>=5?e[2]:void 0};return{errorLoading:function(){return"Nie można załadować wyników."},inputTooLong:function(e){var t=e.input.length-e.maximum;return"Usuń "+t+" "+r(t,n)},inputTooShort:function(e){var t=e.minimum-e.input.length;return"Podaj przynajmniej "+t+" "+r(t,n)},loadingMore:function(){return"Trwa ładowanie…"},maximumSelected:function(n){return"Możesz zaznaczyć tylko "+n.maximum+" "+r(n.maximum,e)},noResults:function(){return"Brak wyników"},searching:function(){return"Trwa wyszukiwanie…"},removeAllItems:function(){return"Usuń wszystkie przedmioty"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ps.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ps",[],function(){return{errorLoading:function(){return"پايلي نه سي ترلاسه کېدای"},inputTooLong:function(n){var e=n.input.length-n.maximum,r="د مهربانۍ لمخي "+e+" توری ړنګ کړئ";return 1!=e&&(r=r.replace("توری","توري")),r},inputTooShort:function(n){return"لږ تر لږه "+(n.minimum-n.input.length)+" يا ډېر توري وليکئ"},loadingMore:function(){return"نوري پايلي ترلاسه کيږي..."},maximumSelected:function(n){var e="تاسو يوازي "+n.maximum+" قلم په نښه کولای سی";return 1!=n.maximum&&(e=e.replace("قلم","قلمونه")),e},noResults:function(){return"پايلي و نه موندل سوې"},searching:function(){return"لټول کيږي..."},removeAllItems:function(){return"ټول توکي لرې کړئ"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/pt-BR.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt-BR",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var n=e.input.length-e.maximum,r="Apague "+n+" caracter";return 1!=n&&(r+="es"),r},inputTooShort:function(e){return"Digite "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"Carregando mais resultados…"},maximumSelected:function(e){var n="Você só pode selecionar "+e.maximum+" ite";return 1==e.maximum?n+="m":n+="ns",n},noResults:function(){return"Nenhum resultado encontrado"},searching:function(){return"Buscando…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/pt.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/pt",[],function(){return{errorLoading:function(){return"Os resultados não puderam ser carregados."},inputTooLong:function(e){var r=e.input.length-e.maximum,n="Por favor apague "+r+" ";return n+=1!=r?"caracteres":"caractere"},inputTooShort:function(e){return"Introduza "+(e.minimum-e.input.length)+" ou mais caracteres"},loadingMore:function(){return"A carregar mais resultados…"},maximumSelected:function(e){var r="Apenas pode seleccionar "+e.maximum+" ";return r+=1!=e.maximum?"itens":"item"},noResults:function(){return"Sem resultados"},searching:function(){return"A procurar…"},removeAllItems:function(){return"Remover todos os itens"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ro.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/ro",[],function(){return{errorLoading:function(){return"Rezultatele nu au putut fi incărcate."},inputTooLong:function(e){var t=e.input.length-e.maximum,n="Vă rugăm să ștergeți"+t+" caracter";return 1!==t&&(n+="e"),n},inputTooShort:function(e){return"Vă rugăm să introduceți "+(e.minimum-e.input.length)+" sau mai multe caractere"},loadingMore:function(){return"Se încarcă mai multe rezultate…"},maximumSelected:function(e){var t="Aveți voie să selectați cel mult "+e.maximum;return t+=" element",1!==e.maximum&&(t+="e"),t},noResults:function(){return"Nu au fost găsite rezultate"},searching:function(){return"Căutare…"},removeAllItems:function(){return"Eliminați toate elementele"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/ru.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/ru",[],function(){function n(n,e,r,u){return n%10<5&&n%10>0&&n%100<5||n%100>20?n%10>1?r:e:u}return{errorLoading:function(){return"Невозможно загрузить результаты"},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Пожалуйста, введите на "+r+" символ";return u+=n(r,"","a","ов"),u+=" меньше"},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Пожалуйста, введите ещё хотя бы "+r+" символ";return u+=n(r,"","a","ов")},loadingMore:function(){return"Загрузка данных…"},maximumSelected:function(e){var r="Вы можете выбрать не более "+e.maximum+" элемент";return r+=n(e.maximum,"","a","ов")},noResults:function(){return"Совпадений не найдено"},searching:function(){return"Поиск…"},removeAllItems:function(){return"Удалить все элементы"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/sk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sk",[],function(){var e={2:function(e){return e?"dva":"dve"},3:function(){return"tri"},4:function(){return"štyri"}};return{errorLoading:function(){return"Výsledky sa nepodarilo načítať."},inputTooLong:function(n){var t=n.input.length-n.maximum;return 1==t?"Prosím, zadajte o jeden znak menej":t>=2&&t<=4?"Prosím, zadajte o "+e[t](!0)+" znaky menej":"Prosím, zadajte o "+t+" znakov menej"},inputTooShort:function(n){var t=n.minimum-n.input.length;return 1==t?"Prosím, zadajte ešte jeden znak":t<=4?"Prosím, zadajte ešte ďalšie "+e[t](!0)+" znaky":"Prosím, zadajte ešte ďalších "+t+" znakov"},loadingMore:function(){return"Načítanie ďalších výsledkov…"},maximumSelected:function(n){return 1==n.maximum?"Môžete zvoliť len jednu položku":n.maximum>=2&&n.maximum<=4?"Môžete zvoliť najviac "+e[n.maximum](!1)+" položky":"Môžete zvoliť najviac "+n.maximum+" položiek"},noResults:function(){return"Nenašli sa žiadne položky"},searching:function(){return"Vyhľadávanie…"},removeAllItems:function(){return"Odstráňte všetky položky"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/sl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sl",[],function(){return{errorLoading:function(){return"Zadetkov iskanja ni bilo mogoče naložiti."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Prosim zbrišite "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},inputTooShort:function(e){var n=e.minimum-e.input.length,t="Prosim vpišite še "+n+" znak";return 2==n?t+="a":1!=n&&(t+="e"),t},loadingMore:function(){return"Nalagam več zadetkov…"},maximumSelected:function(e){var n="Označite lahko največ "+e.maximum+" predmet";return 2==e.maximum?n+="a":1!=e.maximum&&(n+="e"),n},noResults:function(){return"Ni zadetkov."},searching:function(){return"Iščem…"},removeAllItems:function(){return"Odstranite vse elemente"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/sq.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/sq",[],function(){return{errorLoading:function(){return"Rezultatet nuk mund të ngarkoheshin."},inputTooLong:function(e){var n=e.input.length-e.maximum,t="Të lutem fshi "+n+" karakter";return 1!=n&&(t+="e"),t},inputTooShort:function(e){return"Të lutem shkruaj "+(e.minimum-e.input.length)+" ose më shumë karaktere"},loadingMore:function(){return"Duke ngarkuar më shumë rezultate…"},maximumSelected:function(e){var n="Mund të zgjedhësh vetëm "+e.maximum+" element";return 1!=e.maximum&&(n+="e"),n},noResults:function(){return"Nuk u gjet asnjë rezultat"},searching:function(){return"Duke kërkuar…"},removeAllItems:function(){return"Hiq të gjitha sendet"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/sr-Cyrl.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr-Cyrl",[],function(){function n(n,e,r,u){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:u}return{errorLoading:function(){return"Преузимање није успело."},inputTooLong:function(e){var r=e.input.length-e.maximum,u="Обришите "+r+" симбол";return u+=n(r,"","а","а")},inputTooShort:function(e){var r=e.minimum-e.input.length,u="Укуцајте бар још "+r+" симбол";return u+=n(r,"","а","а")},loadingMore:function(){return"Преузимање још резултата…"},maximumSelected:function(e){var r="Можете изабрати само "+e.maximum+" ставк";return r+=n(e.maximum,"у","е","и")},noResults:function(){return"Ништа није пронађено"},searching:function(){return"Претрага…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/sr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sr",[],function(){function n(n,e,r,t){return n%10==1&&n%100!=11?e:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?r:t}return{errorLoading:function(){return"Preuzimanje nije uspelo."},inputTooLong:function(e){var r=e.input.length-e.maximum,t="Obrišite "+r+" simbol";return t+=n(r,"","a","a")},inputTooShort:function(e){var r=e.minimum-e.input.length,t="Ukucajte bar još "+r+" simbol";return t+=n(r,"","a","a")},loadingMore:function(){return"Preuzimanje još rezultata…"},maximumSelected:function(e){var r="Možete izabrati samo "+e.maximum+" stavk";return r+=n(e.maximum,"u","e","i")},noResults:function(){return"Ništa nije pronađeno"},searching:function(){return"Pretraga…"},removeAllItems:function(){return"Уклоните све ставке"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/sv.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/sv",[],function(){return{errorLoading:function(){return"Resultat kunde inte laddas."},inputTooLong:function(n){return"Vänligen sudda ut "+(n.input.length-n.maximum)+" tecken"},inputTooShort:function(n){return"Vänligen skriv in "+(n.minimum-n.input.length)+" eller fler tecken"},loadingMore:function(){return"Laddar fler resultat…"},maximumSelected:function(n){return"Du kan max välja "+n.maximum+" element"},noResults:function(){return"Inga träffar"},searching:function(){return"Söker…"},removeAllItems:function(){return"Ta bort alla objekt"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/th.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/th",[],function(){return{errorLoading:function(){return"ไม่สามารถค้นข้อมูลได้"},inputTooLong:function(n){return"โปรดลบออก "+(n.input.length-n.maximum)+" ตัวอักษร"},inputTooShort:function(n){return"โปรดพิมพ์เพิ่มอีก "+(n.minimum-n.input.length)+" ตัวอักษร"},loadingMore:function(){return"กำลังค้นข้อมูลเพิ่ม…"},maximumSelected:function(n){return"คุณสามารถเลือกได้ไม่เกิน "+n.maximum+" รายการ"},noResults:function(){return"ไม่พบข้อมูล"},searching:function(){return"กำลังค้นข้อมูล…"},removeAllItems:function(){return"ลบรายการทั้งหมด"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/tk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;e.define("select2/i18n/tk",[],function(){return{errorLoading:function(){return"Netije ýüklenmedi."},inputTooLong:function(e){return e.input.length-e.maximum+" harp bozuň."},inputTooShort:function(e){return"Ýene-de iň az "+(e.minimum-e.input.length)+" harp ýazyň."},loadingMore:function(){return"Köpräk netije görkezilýär…"},maximumSelected:function(e){return"Diňe "+e.maximum+" sanysyny saýlaň."},noResults:function(){return"Netije tapylmady."},searching:function(){return"Gözlenýär…"},removeAllItems:function(){return"Remove all items"}}}),e.define,e.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/tr.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/tr",[],function(){return{errorLoading:function(){return"Sonuç yüklenemedi"},inputTooLong:function(n){return n.input.length-n.maximum+" karakter daha girmelisiniz"},inputTooShort:function(n){return"En az "+(n.minimum-n.input.length)+" karakter daha girmelisiniz"},loadingMore:function(){return"Daha fazla…"},maximumSelected:function(n){return"Sadece "+n.maximum+" seçim yapabilirsiniz"},noResults:function(){return"Sonuç bulunamadı"},searching:function(){return"Aranıyor…"},removeAllItems:function(){return"Tüm öğeleri kaldır"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/uk.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/uk",[],function(){function n(n,e,u,r){return n%100>10&&n%100<15?r:n%10==1?e:n%10>1&&n%10<5?u:r}return{errorLoading:function(){return"Неможливо завантажити результати"},inputTooLong:function(e){return"Будь ласка, видаліть "+(e.input.length-e.maximum)+" "+n(e.maximum,"літеру","літери","літер")},inputTooShort:function(n){return"Будь ласка, введіть "+(n.minimum-n.input.length)+" або більше літер"},loadingMore:function(){return"Завантаження інших результатів…"},maximumSelected:function(e){return"Ви можете вибрати лише "+e.maximum+" "+n(e.maximum,"пункт","пункти","пунктів")},noResults:function(){return"Нічого не знайдено"},searching:function(){return"Пошук…"},removeAllItems:function(){return"Видалити всі елементи"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/vi.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/vi",[],function(){return{inputTooLong:function(n){return"Vui lòng xóa bớt "+(n.input.length-n.maximum)+" ký tự"},inputTooShort:function(n){return"Vui lòng nhập thêm từ "+(n.minimum-n.input.length)+" ký tự trở lên"},loadingMore:function(){return"Đang lấy thêm kết quả…"},maximumSelected:function(n){return"Chỉ có thể chọn được "+n.maximum+" lựa chọn"},noResults:function(){return"Không tìm thấy kết quả"},searching:function(){return"Đang tìm…"},removeAllItems:function(){return"Xóa tất cả các mục"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/zh-CN.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-CN",[],function(){return{errorLoading:function(){return"无法载入结果。"},inputTooLong:function(n){return"请删除"+(n.input.length-n.maximum)+"个字符"},inputTooShort:function(n){return"请再输入至少"+(n.minimum-n.input.length)+"个字符"},loadingMore:function(){return"载入更多结果…"},maximumSelected:function(n){return"最多只能选择"+n.maximum+"个项目"},noResults:function(){return"未找到结果"},searching:function(){return"搜索中…"},removeAllItems:function(){return"删除所有项目"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/select2/i18n/zh-TW.js: -------------------------------------------------------------------------------- 1 | /*! Select2 4.0.13 | https://github.com/select2/select2/blob/master/LICENSE.md */ 2 | 3 | !function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var n=jQuery.fn.select2.amd;n.define("select2/i18n/zh-TW",[],function(){return{inputTooLong:function(n){return"請刪掉"+(n.input.length-n.maximum)+"個字元"},inputTooShort:function(n){return"請再輸入"+(n.minimum-n.input.length)+"個字元"},loadingMore:function(){return"載入中…"},maximumSelected:function(n){return"你只能選擇最多"+n.maximum+"項"},noResults:function(){return"沒有找到相符的項目"},searching:function(){return"搜尋中…"},removeAllItems:function(){return"刪除所有項目"}}}),n.define,n.require}(); -------------------------------------------------------------------------------- /web/cpuprofiler/static/admin/js/vendor/xregexp/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2007-2017 Steven Levithan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/all/buffer.js: -------------------------------------------------------------------------------- 1 | let wabt; 2 | let mod_module; 3 | let pump_counter = 0; 4 | let parts; 5 | let pump_part = ""; 6 | let points = []; 7 | 8 | async function calculateLoadBufferSize(memory, clock) { 9 | const resp2 = await fetch("/static/wasm/loadbuffer.wat"); 10 | let text = await resp2.text(); 11 | let wabt = await new WabtModule(); 12 | parts = text.split("here"); 13 | 14 | let pumped = parts[0] + pump_part + parts[1] + pump_part + parts[2]; 15 | 16 | let wabt_module = wabt.parseWat("pumped", pumped, { threads: true }); 17 | mod_module = await wabt_module.toBinary({ 18 | log: false, 19 | canonicalize_lebs: false, 20 | relocatable: false, 21 | write_debug_names: false, 22 | }); 23 | mod_module = await mod_module.buffer.buffer; 24 | wabt_module.destroy(); 25 | mod_module = new WebAssembly.Module(mod_module); 26 | 27 | let finished = 0; 28 | const OUTER_ITERATIONS = 116; 29 | 30 | const finder = new Worker("/static/buffer/loadWorker.js"); 31 | finder.onmessage = function handle(evt) { 32 | let msg = evt.data; 33 | switch (msg.type) { 34 | case "result": 35 | points.push({ x: finished + 16, y: Number(msg.result) }); 36 | finished += 1; 37 | updateProgress(finished / OUTER_ITERATIONS); 38 | // update module 39 | next_iteration(); 40 | // 41 | finder.postMessage({ module: mod_module, memory: memory }); 42 | 43 | if (finished == OUTER_ITERATIONS) { 44 | profiler_results.push(points); 45 | profiler_chart_types.push("/plot/line/"); 46 | 47 | clock.terminate(); 48 | finder.terminate(); 49 | nextProfiler("Single core performance"); 50 | if (stop) return; 51 | calculateSinglePerformance(); 52 | } 53 | break; 54 | default: 55 | } 56 | }; 57 | finder.postMessage({ module: mod_module, memory: memory }); 58 | } 59 | 60 | async function next_iteration() { 61 | wabt = await new WabtModule(); 62 | 63 | pump_counter += 128; 64 | pump_part += `\n(i32.add (i32.load (i32.const ${512 + pump_counter})))\n`; 65 | pumped = parts[0] + pump_part + parts[1] + pump_part + parts[2]; 66 | 67 | let wabt_module = wabt.parseWat("pumped", pumped, { threads: true }); 68 | mod_module = await wabt_module.toBinary({ 69 | log: false, 70 | canonicalize_lebs: false, 71 | relocatable: false, 72 | write_debug_names: false, 73 | }); 74 | mod_module = await mod_module.buffer.buffer; 75 | wabt_module.destroy(); 76 | mod_module = new WebAssembly.Module(mod_module); 77 | } 78 | 79 | function concatenate(resultConstructor, ...arrays) { 80 | let totalLength = 0; 81 | for (const arr of arrays) { 82 | totalLength += arr.length; 83 | } 84 | const result = new resultConstructor(totalLength); 85 | let offset = 0; 86 | for (const arr of arrays) { 87 | result.set(arr, offset); 88 | offset += arr.length; 89 | } 90 | return result; 91 | } 92 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/all/cores.js: -------------------------------------------------------------------------------- 1 | const CORES_MAX_WORKERS = 33; 2 | 3 | let cores_workers = []; 4 | let cores_tmp_results = []; 5 | let cores_finishedWorkers = 0; 6 | 7 | let cores_start = 0; 8 | let cores_end = 0; 9 | let cores_amountOfWorkers = 1; 10 | let cores_points = []; 11 | 12 | function run(workersAmount, base, mod) { 13 | cores_tmp_results = new Array(workersAmount).fill(0); 14 | cores_start = performance.now(); 15 | for (let i = 0; i < workersAmount; i++) { 16 | let worker = new Worker("/static/misc/cores/worker.js"); 17 | worker.onmessage = callback; 18 | cores_workers.push(worker); 19 | } 20 | 21 | for (let i = 0; i < workersAmount; i++) { 22 | let data = {}; 23 | data.workerId = i; 24 | data.base = base; 25 | data.power = 128000000 / 4; 26 | data.mod = mod; 27 | cores_workers[i].postMessage(data); 28 | } 29 | } 30 | 31 | function callback(event) { 32 | let data = event.data; 33 | cores_workers[data.workerId].terminate(); 34 | cores_tmp_results[data.workerId] = data.result; 35 | 36 | if (++cores_finishedWorkers == cores_amountOfWorkers) { 37 | cores_end = performance.now() - cores_start; 38 | 39 | cores_points.push({ x: cores_amountOfWorkers, y: cores_end }); 40 | 41 | if (cores_amountOfWorkers == 1) cores_amountOfWorkers += 1; 42 | else if (cores_amountOfWorkers < 32) cores_amountOfWorkers += 2; 43 | else cores_amountOfWorkers += 16; 44 | 45 | if (cores_amountOfWorkers < CORES_MAX_WORKERS) { 46 | cores_tmp_results = []; 47 | cores_workers = []; 48 | cores_finishedWorkers = 0; 49 | updateProgress(cores_amountOfWorkers / CORES_MAX_WORKERS); 50 | run(cores_amountOfWorkers, 2, 97777); 51 | } 52 | 53 | if (cores_amountOfWorkers >= CORES_MAX_WORKERS) { 54 | cores_amountOfWorkers = 0; 55 | profiler_results.push(cores_points); 56 | profiler_chart_types.push("/plot/line/"); 57 | profiler_times.push(performance.now() - tmp); 58 | 59 | updateProfiler(""); 60 | updateProgress(1); 61 | updateTotalProgress(1); 62 | if (stop) return; 63 | createChartsAndUpload(); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/all/performance.js: -------------------------------------------------------------------------------- 1 | async function calculateSinglePerformance() { 2 | let points = []; 3 | 4 | let ITERATIONS = 500; 5 | let counter; 6 | let start; 7 | 8 | for (let i = 0; i < ITERATIONS; i++) { 9 | counter = 0; 10 | start = performance.now() + 1; 11 | while (start > performance.now()) { 12 | counter += 1; 13 | } 14 | 15 | points.push({ x: Number(i), y: Number(counter) }); 16 | } 17 | 18 | updateProgress(1 / 3); 19 | 20 | await new Promise((r) => setTimeout(r, 100)); 21 | 22 | for (let i = 0; i < ITERATIONS; i++) { 23 | counter = 0; 24 | start = performance.now() + 1; 25 | while (start > performance.now()) { 26 | counter += 1; 27 | } 28 | 29 | points.push({ x: Number(i + ITERATIONS), y: Number(counter) }); 30 | } 31 | 32 | updateProgress(2 / 3); 33 | 34 | await new Promise((r) => setTimeout(r, 100)); 35 | 36 | for (let i = 0; i < ITERATIONS; i++) { 37 | counter = 0; 38 | start = performance.now() + 1; 39 | while (start > performance.now()) { 40 | counter += 1; 41 | } 42 | 43 | points.push({ x: Number(i + ITERATIONS * 2), y: Number(counter) }); 44 | } 45 | 46 | updateProgress(1); 47 | 48 | profiler_results.push(points); 49 | profiler_chart_types.push("/plot/line/"); 50 | 51 | nextProfiler("Multi core performance"); 52 | if (stop) return; 53 | calculateMultiPerformance(); 54 | } 55 | 56 | async function calculateMultiPerformance() { 57 | let WORKERS = 10; 58 | const ITERATIONS = 10000; 59 | let results = new Array(WORKERS).fill({}); 60 | let workers = []; 61 | let finishedWorkers = 0; 62 | 63 | for (let i = 0; i < WORKERS; i++) { 64 | let worker = new Worker("/static/performance/performanceWorker.js"); 65 | worker.onmessage = function (event) { 66 | let data = event.data; 67 | workers[data.workerId].terminate(); 68 | results[data.workerId] = data.points; 69 | finishedWorkers += 1; 70 | updateProgress(finishedWorkers / WORKERS); 71 | 72 | if (finishedWorkers == WORKERS) { 73 | profiler_results.push(results); 74 | profiler_chart_types.push("/plot/multiline/"); 75 | 76 | nextProfiler("Number of cores"); 77 | if (stop) return; 78 | run(1, 2, 97777); 79 | } 80 | }; 81 | workers.push(worker); 82 | } 83 | 84 | for (let i = 0; i < WORKERS; i++) { 85 | workers[i].postMessage({ workerId: i, iterations: ITERATIONS }); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/buffer/loadWorker.js: -------------------------------------------------------------------------------- 1 | const ITERATIONS = 8192 * 4; 2 | const P1 = 512 + 128 * 120; 3 | const P2 = P1 + ITERATIONS * 16; 4 | const RANDOM = true; 5 | const INNER_ITERATIONS = 128; 6 | const WARMUP = 12000; 7 | 8 | self.onmessage = async function start(evt) { 9 | // Prepare wasm instance 10 | const { module, memory } = evt.data; 11 | 12 | const instance = new WebAssembly.Instance(module, { 13 | env: { mem: memory }, 14 | console: { 15 | log: function (arg) { 16 | console.log(arg); 17 | }, 18 | }, 19 | }); 20 | // Memory view 21 | const view = new DataView(memory.buffer); 22 | 23 | await new Promise((r) => setTimeout(r, 10)); // allow counter to start 24 | 25 | prepareList(ITERATIONS * 2, view, P1); 26 | prepareList(ITERATIONS * 2, view, P2); 27 | 28 | for (let i = 0; i < WARMUP; i++) instance.exports.routine(P1, P2, 20); 29 | 30 | prepareList(ITERATIONS * 2, view, P1); 31 | prepareList(ITERATIONS * 2, view, P2); 32 | let result = 0n; 33 | for (let i = 0; i < INNER_ITERATIONS; i++) 34 | result += instance.exports.routine(P1, P2, ITERATIONS); 35 | 36 | postMessage({ type: "result", result: result / BigInt(INNER_ITERATIONS) }); 37 | }; 38 | 39 | function prepareList(size, view, start) { 40 | // init [0, ... , size - 1] 41 | let indices = []; 42 | for (let i = 0; i < size; i++) { 43 | indices.push(i); 44 | } 45 | 46 | // randomize indices 47 | if (RANDOM) { 48 | for (let i = 0; i < size; i++) { 49 | let j = i + getRandomInt(0, size - i - 1); 50 | // swap 51 | if (j != i) [indices[j], indices[i]] = [indices[i], indices[j]]; 52 | } 53 | } 54 | 55 | // index to address conversion 56 | indices = indices.map((x) => start + x * 4); 57 | 58 | // write linked list to memory 59 | for (let i = 1; i < size; i++) { 60 | view.setUint32(indices[i - 1], indices[i], true); 61 | } 62 | view.setUint32(indices[size - 1], indices[0], true); 63 | } 64 | 65 | function getRandomInt(min, max) { 66 | return Math.floor(Math.random() * (max - min + 1)) + min; 67 | } 68 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/cache/assoFinder.js: -------------------------------------------------------------------------------- 1 | // Constants 2 | const P = 4096; 3 | const KB = 1024; 4 | const MB = 1024 * 1024; 5 | const ITERATIONS = BigInt(MB * 64); 6 | const RANDOM = true; 7 | const MAXSIZE = 32; 8 | 9 | const START = 512; 10 | 11 | self.onmessage = async function start(evt) { 12 | // Prepare wasm instance 13 | const { module, memory } = evt.data; 14 | const instance = new WebAssembly.Instance(module, { 15 | env: { mem: memory }, 16 | console: { 17 | log: function (arg) { 18 | console.log(arg); 19 | }, 20 | }, 21 | }); 22 | 23 | // Memory view 24 | const view = new DataView(memory.buffer); 25 | 26 | await new Promise((r) => setTimeout(r, 10)); // allow counter to start 27 | 28 | const sizes = [ 29 | 1 * KB, 30 | 4 * KB, 31 | 8 * KB, 32 | 16 * KB, 33 | 32 * KB, 34 | 64 * KB, 35 | 128 * KB, 36 | 256 * KB, 37 | 512 * KB, 38 | 1 * MB, 39 | 2 * MB, 40 | ]; 41 | 42 | let points = []; 43 | 44 | for (let size = 1; size < MAXSIZE; size++) { 45 | prepareList(size, view); 46 | //console.log(instance.exports.check(START)); 47 | instance.exports.iterate(START, ITERATIONS); 48 | let result = instance.exports.iterate(START, ITERATIONS); 49 | // log("Iteration " + size + " of " + MAXSIZE); 50 | postMessage({ type: "progress", value: size / MAXSIZE }); 51 | points.push({ x: Number(size), y: Number(result) }); 52 | } 53 | 54 | postMessage({ type: "progress", value: 1 }); 55 | 56 | postMessage({ type: "results", points: points }); 57 | 58 | postMessage({ type: "terminate" }); 59 | }; 60 | 61 | function prepareList(size, view) { 62 | // init [0, ... , 32 * KB * (size - 1)] 63 | let indices = []; 64 | for (let i = 0; i < size; i++) { 65 | indices.push(i * 32 * KB); 66 | } 67 | 68 | // randomize indices 69 | if (RANDOM) { 70 | for (let i = 0; i < size; i++) { 71 | let j = i + getRandomInt(0, size - i - 1); 72 | // swap 73 | if (j != i) [indices[j], indices[i]] = [indices[i], indices[j]]; 74 | } 75 | } 76 | 77 | // index to address conversion 78 | indices = indices.map((x) => START + x); 79 | 80 | // write linked list to memory 81 | for (let i = 1; i < size; i++) { 82 | view.setUint32(indices[i - 1], indices[i], true); 83 | } 84 | view.setUint32(indices[size - 1], indices[0], true); 85 | } 86 | 87 | function getRandomInt(min, max) { 88 | return Math.floor(Math.random() * (max - min + 1)) + min; 89 | } 90 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/cache/cacheAssociativity.js: -------------------------------------------------------------------------------- 1 | async function calculateCacheAssociativity(CanvasJS) { 2 | document.getElementById("startButton").disabled = true; 3 | 4 | // Shared memory 5 | memory = new WebAssembly.Memory({ 6 | initial: amountOfPages, 7 | maximum: amountOfPages, 8 | shared: true, 9 | }); 10 | 11 | const clock = await startClockWorker(); 12 | 13 | const resp2 = await fetch("/static/wasm/size.wasm"); 14 | const bin2 = await resp2.arrayBuffer(); 15 | const module2 = new WebAssembly.Module(bin2); 16 | const finder = new Worker("/static/cache/assoFinder.js"); 17 | finder.onmessage = function handle(evt) { 18 | let msg = evt.data; 19 | switch (msg.type) { 20 | case "progress": 21 | updateProgress(msg.value); 22 | break; 23 | case "log": 24 | log(...msg.str); 25 | break; 26 | case "terminate": 27 | clock.terminate(); 28 | finder.terminate(); 29 | break; 30 | case "results": 31 | var chart = new CanvasJS.Chart("chartContainer", { 32 | animationEnabled: true, 33 | theme: "light2", 34 | data: [ 35 | { 36 | type: "line", 37 | indexLabelFontSize: 16, 38 | dataPoints: msg.points, 39 | }, 40 | ], 41 | }); 42 | chart.render(); 43 | break; 44 | default: 45 | } 46 | }; 47 | finder.postMessage({ module: module2, memory: memory }); 48 | } 49 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/cache/cacheSize.js: -------------------------------------------------------------------------------- 1 | async function calculateCacheSize(CanvasJS) { 2 | document.getElementById("startButton").disabled = true; 3 | 4 | // Shared memory 5 | memory = new WebAssembly.Memory({ 6 | initial: amountOfPages, 7 | maximum: amountOfPages, 8 | shared: true, 9 | }); 10 | 11 | const clock = await startClockWorker(); 12 | 13 | const resp2 = await fetch("/static/wasm/size.wasm"); 14 | const bin2 = await resp2.arrayBuffer(); 15 | const module2 = new WebAssembly.Module(bin2); 16 | const finder = new Worker("/static/cache/sizeFinder.js"); 17 | finder.onmessage = function handle(evt) { 18 | let msg = evt.data; 19 | switch (msg.type) { 20 | case "progress": 21 | updateProgress(msg.value); 22 | break; 23 | case "log": 24 | log(...msg.str); 25 | break; 26 | case "terminate": 27 | clock.terminate(); 28 | finder.terminate(); 29 | break; 30 | 31 | case "results": 32 | console.log(msg.points.slice(0, 128)); 33 | console.log(msg.points.slice(129)); 34 | var chartSmall = new CanvasJS.Chart("chartContainerSmall", { 35 | animationEnabled: true, 36 | theme: "light2", 37 | data: [ 38 | { 39 | type: "line", 40 | indexLabelFontSize: 16, 41 | dataPoints: msg.points.slice(0, 128), 42 | }, 43 | ], 44 | }); 45 | chartSmall.render(); 46 | var chartLarge = new CanvasJS.Chart("chartContainerLarge", { 47 | animationEnabled: true, 48 | theme: "light2", 49 | data: [ 50 | { 51 | type: "line", 52 | indexLabelFontSize: 16, 53 | dataPoints: msg.points.slice(129), 54 | }, 55 | ], 56 | }); 57 | chartLarge.render(); 58 | break; 59 | default: 60 | } 61 | }; 62 | finder.postMessage({ module: module2, memory: memory, large: true }); 63 | } 64 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/cache/sizeFinder.js: -------------------------------------------------------------------------------- 1 | // Constants 2 | const P = 4096; 3 | const KB = 1024; 4 | const MB = 1024 * 1024; 5 | //const ITERATIONS = BigInt(MB * 64); 6 | const ITERATIONS = BigInt(MB * 16); 7 | const RANDOM = true; 8 | 9 | const START = 512; 10 | 11 | self.onmessage = async function start(evt) { 12 | // Prepare wasm instance 13 | const { module, memory, large } = evt.data; 14 | const instance = new WebAssembly.Instance(module, { 15 | env: { mem: memory }, 16 | console: { 17 | log: function (arg) { 18 | console.log(arg); 19 | }, 20 | }, 21 | }); 22 | // Memory view 23 | const view = new DataView(memory.buffer); 24 | 25 | await new Promise((r) => setTimeout(r, 10)); // allow counter to start 26 | 27 | let sizes = [1 * KB]; 28 | 29 | for (let i = 4; i < 513; i += 4) sizes.push(i * KB); 30 | 31 | sizes.push(Number(1 * MB)); 32 | 33 | if (large) { 34 | for (let i = 2; i < 33; i += 2) sizes.push(Number(i * MB)); 35 | } 36 | 37 | let points = []; 38 | 39 | for (let i = 0; i < sizes.length; i++) { 40 | prepareList(sizes[i] / 4, view); 41 | instance.exports.iterate(START, ITERATIONS); 42 | let result = instance.exports.iterate(START, ITERATIONS); 43 | postMessage({ type: "progress", value: i / sizes.length }); 44 | points.push({ x: Number(sizes[i]), y: Number(result) }); 45 | } 46 | 47 | postMessage({ type: "progress", value: 1 }); 48 | 49 | postMessage({ type: "results", points: points }); 50 | 51 | postMessage({ type: "terminate" }); 52 | }; 53 | 54 | function prepareList(size, view) { 55 | // init [0, ... , size - 1] 56 | let indices = []; 57 | for (let i = 0; i < size; i++) { 58 | indices.push(i); 59 | } 60 | 61 | // randomize indices 62 | if (RANDOM) { 63 | for (let i = 0; i < size; i++) { 64 | let j = i + getRandomInt(0, size - i - 1); 65 | // swap 66 | if (j != i) [indices[j], indices[i]] = [indices[i], indices[j]]; 67 | } 68 | } 69 | 70 | // index to address conversion 71 | indices = indices.map((x) => START + x * 4); 72 | 73 | // write linked list to memory 74 | for (let i = 1; i < size; i++) { 75 | view.setUint32(indices[i - 1], indices[i], true); 76 | } 77 | view.setUint32(indices[size - 1], indices[0], true); 78 | } 79 | 80 | function getRandomInt(min, max) { 81 | return Math.floor(Math.random() * (max - min + 1)) + min; 82 | } 83 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/favicon.ico -------------------------------------------------------------------------------- /web/cpuprofiler/static/main.js: -------------------------------------------------------------------------------- 1 | let profiler_times = []; 2 | let profiler_results = []; 3 | let profiler_names = []; 4 | let profiler_chart_types = []; 5 | const PROFILERS = 13; 6 | let tmp; 7 | let LARGE = true; 8 | 9 | async function startProfilers() { 10 | if (document.getElementById("model").value == "") { 11 | document.getElementById("model").classList.add("is-invalid"); 12 | return; 13 | } 14 | 15 | if (document.getElementById("workerid").value == "") { 16 | document.getElementById("workerid").classList.add("is-invalid"); 17 | return; 18 | } 19 | 20 | window.scrollBy(0, 10000); 21 | 22 | interval_id = setInterval(dec_timer, 1000); 23 | 24 | document.getElementById("model").classList.remove("is-invalid"); 25 | document.getElementById("model").setAttribute("readonly", true); 26 | 27 | document.getElementById("workerid").classList.remove("is-invalid"); 28 | document.getElementById("workerid").setAttribute("readonly", true); 29 | 30 | document.getElementById("lowMemory").disabled = true; 31 | document.getElementById("startButton").disabled = true; 32 | 33 | // Shared memory 34 | memory = new WebAssembly.Memory({ 35 | initial: amountOfPages, 36 | maximum: amountOfPages, 37 | shared: true, 38 | }); 39 | 40 | const clock = await startClockWorker(); 41 | 42 | tmp = performance.now(); 43 | profiler_names.push("Pagesize"); 44 | updateProfiler("Pagesize"); 45 | pagesize(memory, clock); 46 | } 47 | 48 | async function checkChargingStatus() { 49 | let status = document.getElementById("chargingstatus"); 50 | if (navigator.getBattery) { 51 | navigator.getBattery().then(function (battery) { 52 | let button = document.getElementById("chargingbutton"); 53 | button.classList.remove("btn-secondary"); 54 | button.classList.remove("btn-success"); 55 | button.classList.remove("btn-danger"); 56 | if (battery.charging) { 57 | status.innerText = "Charging!"; 58 | button.classList.add("btn-success"); 59 | } else { 60 | status.innerText = "Not charging?"; 61 | button.classList.add("btn-danger"); 62 | } 63 | }); 64 | } else { 65 | status.innerText = "Still unknown"; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/misc/bits/bits.js: -------------------------------------------------------------------------------- 1 | async function calculateBits(CanvasJS) { 2 | document.getElementById("startButton").disabled = true; 3 | 4 | let points = []; 5 | 6 | // Shared memory 7 | memory = new WebAssembly.Memory({ 8 | initial: amountOfPages, 9 | maximum: amountOfPages, 10 | shared: true, 11 | }); 12 | 13 | // Clock thread 14 | const resp = await fetch("/static/wasm/bits.wasm"); 15 | const bin = await resp.arrayBuffer(); 16 | const module = new WebAssembly.Module(bin); 17 | const instance = new WebAssembly.Instance(module, { 18 | env: { mem: memory }, 19 | console: { 20 | log: function (arg) { 21 | console.log(arg); 22 | }, 23 | }, 24 | }); 25 | 26 | let start = performance.now(); 27 | 28 | for (let i = 0; i < 10000000; i++) { 29 | instance.exports.test8(); 30 | } 31 | 32 | let time = performance.now() - start; 33 | points.push({ y: Number(time), label: "8" }); 34 | 35 | updateProgress(0.5); 36 | 37 | start = performance.now(); 38 | 39 | for (let i = 0; i < 10000000; i++) { 40 | instance.exports.test9(); 41 | } 42 | 43 | time = performance.now() - start; 44 | points.push({ y: Number(time), label: "9" }); 45 | 46 | updateProgress(1); 47 | 48 | var chart = new CanvasJS.Chart("chartContainer", { 49 | animationEnabled: true, 50 | theme: "light2", 51 | data: [ 52 | { 53 | type: "column", 54 | indexLabelFontSize: 16, 55 | dataPoints: points, 56 | }, 57 | ], 58 | }); 59 | chart.render(); 60 | } 61 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/misc/cores/cores.js: -------------------------------------------------------------------------------- 1 | // Idea: http://pmav.eu/stuff/javascript-webworkers/ 2 | const MAX = 65; 3 | let points = []; 4 | 5 | let workers = []; 6 | let results = []; 7 | let finishedWorkers = 0; 8 | let start = 0; 9 | let end = 0; 10 | let amountOfWorkers = 1; 11 | let endResult = 1; 12 | let canvasLib; 13 | 14 | function countCores(CanvasJS) { 15 | document.getElementById("startButton").disabled = true; 16 | 17 | canvasLib = CanvasJS; 18 | run(amountOfWorkers, 2, 2048000000, 97777); 19 | } 20 | 21 | function run(workersAmount, base, power, mod) { 22 | results = new Array(workersAmount).fill(0); 23 | 24 | for (let i = 0; i < workersAmount; i++) { 25 | let worker = new Worker("/static/misc/cores/worker.js"); 26 | worker.onmessage = callback; 27 | workers.push(worker); 28 | } 29 | 30 | start = performance.now(); 31 | 32 | for (let i = 0; i < workersAmount; i++) { 33 | let data = {}; 34 | data.workerId = i; 35 | data.base = base; 36 | data.power = 128000000 / 4; 37 | data.mod = mod; 38 | workers[i].postMessage(data); 39 | } 40 | } 41 | 42 | function callback(event) { 43 | let data = event.data; 44 | workers[data.workerId].terminate(); 45 | results[data.workerId] = data.result; 46 | 47 | if (++finishedWorkers == amountOfWorkers) { 48 | end = performance.now() - start; 49 | 50 | for (let i = 0; i < results.length; i++) { 51 | endResult = (endResult * results[i]) % data.mod; 52 | } 53 | 54 | points.push({ x: amountOfWorkers, y: end }); 55 | 56 | if (amountOfWorkers == 1) amountOfWorkers += 1; 57 | else if (amountOfWorkers < 32) amountOfWorkers += 2; 58 | else amountOfWorkers += 16; 59 | 60 | if (amountOfWorkers < MAX) { 61 | results = []; 62 | workers = []; 63 | endResult = 1; 64 | finishedWorkers = 0; 65 | updateProgress(amountOfWorkers / MAX); 66 | run(amountOfWorkers, 2, 2048000000, 97777); 67 | } 68 | 69 | if (amountOfWorkers >= MAX) { 70 | updateProgress(1); 71 | var chart = new canvasLib.Chart("chartContainer", { 72 | animationEnabled: true, 73 | theme: "light2", 74 | data: [ 75 | { 76 | type: "line", 77 | indexLabelFontSize: 16, 78 | dataPoints: points, 79 | }, 80 | ], 81 | }); 82 | chart.render(); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/misc/cores/worker.js: -------------------------------------------------------------------------------- 1 | onmessage = function (event) { 2 | let data = event.data; 3 | 4 | let response = {}; 5 | response.workerId = data.workerId; 6 | response.base = data.base; 7 | response.power = data.power; 8 | response.mod = data.mod; 9 | response.result = power(data.base, data.power, data.mod); 10 | 11 | postMessage(response); 12 | 13 | return; 14 | }; 15 | 16 | function power(base, power, mod) { 17 | if (power == 0) return 1; 18 | let total = 1; 19 | let a = 12345678; 20 | 21 | for (let i = 0; i < power; i++) { 22 | total = (total ^ a) << 1; 23 | total = (total * base) % mod; 24 | } 25 | 26 | return total; 27 | } 28 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/misc/pagesize/pageSize.js: -------------------------------------------------------------------------------- 1 | async function calculatePageSize(CanvasJS) { 2 | document.getElementById("startButton").disabled = true; 3 | 4 | // Shared memory 5 | memory = new WebAssembly.Memory({ 6 | initial: amountOfPages, 7 | maximum: amountOfPages, 8 | shared: true, 9 | }); 10 | 11 | const clock = await startClockWorker(); 12 | 13 | const resp2 = await fetch("/static/wasm/pagesize.wasm"); 14 | const bin2 = await resp2.arrayBuffer(); 15 | const module2 = new WebAssembly.Module(bin2); 16 | const finder = new Worker("/static/misc/pagesize/pagesizeFinder.js"); 17 | finder.onmessage = function handle(evt) { 18 | let msg = evt.data; 19 | switch (msg.type) { 20 | case "progress": 21 | updateProgress(msg.value); 22 | break; 23 | case "log": 24 | log(...msg.str); 25 | break; 26 | case "terminate": 27 | clock.terminate(); 28 | finder.terminate(); 29 | break; 30 | 31 | case "results": 32 | var chart = new CanvasJS.Chart("chartContainer", { 33 | animationEnabled: true, 34 | theme: "light2", 35 | data: [ 36 | { 37 | type: "line", 38 | indexLabelFontSize: 16, 39 | dataPoints: msg.points, 40 | }, 41 | ], 42 | }); 43 | chart.render(); 44 | break; 45 | default: 46 | } 47 | }; 48 | finder.postMessage({ module: module2, memory: memory }); 49 | } 50 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/misc/pagesize/pagesizeFinder.js: -------------------------------------------------------------------------------- 1 | // Constants 2 | const KB = 1024; 3 | const MB = 1024 * 1024; 4 | const MAXSIZE = MB + 100; 5 | 6 | const START = 512; 7 | 8 | self.onmessage = async function start(evt) { 9 | // Prepare wasm instance 10 | const { module, memory } = evt.data; 11 | const instance = new WebAssembly.Instance(module, { 12 | env: { mem: memory }, 13 | console: { 14 | log: function (arg) { 15 | console.log(arg); 16 | }, 17 | }, 18 | }); 19 | 20 | await new Promise((r) => setTimeout(r, 10)); // allow counter to start 21 | 22 | let points = []; 23 | 24 | for (let size = 0; START + size * 4 < MAXSIZE; size++) { 25 | let result = instance.exports.maccess(START + size * 4); 26 | postMessage({ type: "progress", value: size / (MAXSIZE - START) }); 27 | points.push({ x: Number(START + size * 4), y: Number(result) }); 28 | } 29 | 30 | postMessage({ type: "progress", value: 1 }); 31 | 32 | postMessage({ type: "results", points: points }); 33 | 34 | postMessage({ type: "terminate" }); 35 | }; 36 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/misc/prefetcher/prefetch.js: -------------------------------------------------------------------------------- 1 | async function calculatePrefetcherPresence(CanvasJS) { 2 | document.getElementById("startButton").disabled = true; 3 | 4 | // Shared memory 5 | memory = new WebAssembly.Memory({ 6 | initial: amountOfPages, 7 | maximum: amountOfPages, 8 | shared: true, 9 | }); 10 | 11 | const clock = await startClockWorker(); 12 | 13 | const resp2 = await fetch("/static/wasm/prefetch.wasm"); 14 | const bin2 = await resp2.arrayBuffer(); 15 | const module2 = new WebAssembly.Module(bin2); 16 | const finder = new Worker("/static/misc/prefetcher/prefetchWorker.js"); 17 | finder.onmessage = function handle(evt) { 18 | let msg = evt.data; 19 | switch (msg.type) { 20 | case "progress": 21 | updateProgress(msg.value); 22 | break; 23 | case "log": 24 | log(...msg.str); 25 | break; 26 | case "terminate": 27 | clock.terminate(); 28 | finder.terminate(); 29 | break; 30 | 31 | case "results": 32 | var chart = new CanvasJS.Chart("chartContainer", { 33 | animationEnabled: true, 34 | theme: "light2", 35 | data: [ 36 | { 37 | type: "column", 38 | indexLabelFontSize: 16, 39 | dataPoints: msg.points, 40 | }, 41 | ], 42 | }); 43 | chart.render(); 44 | break; 45 | default: 46 | } 47 | }; 48 | finder.postMessage({ module: module2, memory: memory }); 49 | } 50 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/misc/prefetcher/prefetchWorker.js: -------------------------------------------------------------------------------- 1 | // Constants 2 | const KB = 1024; 3 | const MB = 1024 * 1024; 4 | const MAXSIZE = 128 * MB; 5 | const RANDOM = true; 6 | const ENTRIES = KB; 7 | const PAGESIZE = 4096; 8 | const START = 512; 9 | const FENCE = 200; 10 | 11 | self.onmessage = async function start(evt) { 12 | // Prepare wasm instance 13 | const { module, memory } = evt.data; 14 | const instance = new WebAssembly.Instance(module, { 15 | env: { mem: memory }, 16 | console: { 17 | log: function (arg) { 18 | console.log(arg); 19 | }, 20 | }, 21 | }); 22 | 23 | const view = new DataView(memory.buffer); 24 | 25 | await new Promise((r) => setTimeout(r, 10)); // allow counter to start 26 | 27 | let points = []; 28 | let time = 0n; 29 | 30 | let indices = prepareList(ENTRIES, START, view); 31 | 32 | for (let i = 0; i < ENTRIES; i++) { 33 | time += instance.exports.maccess(indices[i], 16, FENCE); 34 | postMessage({ type: "progress", value: i / (ENTRIES * 3) }); 35 | } 36 | 37 | points.push({ y: Number(time), label: "One cache line" }); 38 | 39 | time = 0n; 40 | indices = prepareList(ENTRIES, START + ENTRIES * 256, view); 41 | 42 | for (let i = 0; i < ENTRIES; i++) { 43 | time += instance.exports.maccess(indices[i], 64, FENCE); 44 | postMessage({ type: "progress", value: (i + ENTRIES) / (ENTRIES * 3) }); 45 | } 46 | 47 | points.push({ y: Number(time), label: "Two cache lines" }); 48 | 49 | time = 0n; 50 | indices = prepareList(ENTRIES, START + ENTRIES * 256, view); 51 | 52 | for (let i = 0; i < ENTRIES; i++) { 53 | time += instance.exports.maccess(indices[i], 128, FENCE); 54 | postMessage({ type: "progress", value: (i + ENTRIES * 2) / (ENTRIES * 3) }); 55 | } 56 | 57 | points.push({ y: Number(time), label: "Far cache lines" }); 58 | 59 | postMessage({ type: "progress", value: 1 }); 60 | 61 | postMessage({ type: "results", points: points }); 62 | 63 | postMessage({ type: "terminate" }); 64 | }; 65 | 66 | function prepareList(size, start, view) { 67 | let indices = []; 68 | for (let i = 0; i < size; i++) { 69 | indices.push(i * 256); 70 | } 71 | 72 | // randomize indices 73 | if (RANDOM) { 74 | for (let i = 0; i < size; i++) { 75 | let j = i + getRandomInt(0, size - i - 1); 76 | // swap 77 | if (j != i) [indices[j], indices[i]] = [indices[i], indices[j]]; 78 | } 79 | } 80 | 81 | indices = indices.map((x) => start + x); 82 | 83 | return indices; 84 | } 85 | 86 | function getRandomInt(min, max) { 87 | return Math.floor(Math.random() * (max - min + 1)) + min; 88 | } 89 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/misc/timer/precision.js: -------------------------------------------------------------------------------- 1 | async function calculatePrecision(CanvasJS) { 2 | document.getElementById("startButton").disabled = true; 3 | 4 | // Shared memory 5 | memory = new WebAssembly.Memory({ 6 | initial: amountOfPages, 7 | maximum: amountOfPages, 8 | shared: true, 9 | }); 10 | 11 | const clock = await startClockWorker(); 12 | 13 | const view = new DataView(memory.buffer); 14 | const ITERATIONS = 3; 15 | const INNER_ITERATIONS = 1000; 16 | let pointsDiff = []; 17 | let pointsAbs = []; 18 | 19 | await new Promise((r) => setTimeout(r, 1000)); 20 | 21 | for (let j = 0; j < INNER_ITERATIONS; j++) { 22 | let tmp = view.getBigUint64(0, true); 23 | view.setBigUint64(0, tmp + 1n, true); 24 | } 25 | 26 | let totalStart = view.getBigUint64(256, true); 27 | for (let i = 0; i < ITERATIONS; i++) { 28 | let start = view.getBigUint64(256, true); 29 | 30 | await new Promise((r) => setTimeout(r, 1000)); 31 | // for (let j = 0; j < INNER_ITERATIONS; j++) { 32 | // let tmp = view.getBigUint64(0, true); 33 | // view.setBigUint64(0, tmp + 1n, true); 34 | // } 35 | 36 | let end = view.getBigUint64(256, true); 37 | // pointsDiff.push({ x: i, y: Number(end - start) }); 38 | // pointsAbs.push({ x: i, y: Number(end - totalStart) }); 39 | pointsDiff.push({ y: Number(end - start), label: "Iteration " + i }); 40 | updateProgress(i / ITERATIONS); 41 | } 42 | 43 | updateProgress(1); 44 | clock.terminate(); 45 | 46 | var chartSmall = new CanvasJS.Chart("chartContainer", { 47 | animationEnabled: true, 48 | theme: "light2", 49 | data: [ 50 | { 51 | type: "column", 52 | indexLabelFontSize: 16, 53 | dataPoints: pointsDiff, 54 | }, 55 | ], 56 | }); 57 | chartSmall.render(); 58 | 59 | // var chartLarge = new CanvasJS.Chart("chartContainerLarge", { 60 | // animationEnabled: true, 61 | // theme: "light2", 62 | // data: [ 63 | // { 64 | // type: "line", 65 | // indexLabelFontSize: 16, 66 | // dataPoints: pointsAbs, 67 | // }, 68 | // ], 69 | // }); 70 | // chartLarge.render(); 71 | } 72 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/performance/memory.js: -------------------------------------------------------------------------------- 1 | let finished = 0; 2 | let result = []; 3 | let clock; 4 | let finder1; 5 | let finder2; 6 | 7 | async function calculateMemoryLatencies(CanvasJS) { 8 | document.getElementById("startButton").disabled = true; 9 | 10 | // Shared memory 11 | memory = new WebAssembly.Memory({ 12 | initial: amountOfPages, 13 | maximum: amountOfPages, 14 | shared: true, 15 | }); 16 | 17 | clock = await startClockWorker(); 18 | 19 | const resp2 = await fetch("/static/wasm/pagesize.wasm"); 20 | const bin2 = await resp2.arrayBuffer(); 21 | const module2 = new WebAssembly.Module(bin2); 22 | finder1 = new Worker("/static/performance/memoryWorker.js"); 23 | finder2 = new Worker("/static/performance/memoryWorker.js"); 24 | 25 | finder1.onmessage = handle; 26 | finder2.onmessage = handle; 27 | 28 | finder1.postMessage({ module: module2, memory: memory }); 29 | finder2.postMessage({ module: module2, memory: memory }); 30 | } 31 | 32 | function handle(evt) { 33 | let msg = evt.data; 34 | switch (msg.type) { 35 | case "progress": 36 | updateProgress(msg.value); 37 | break; 38 | case "log": 39 | log(...msg.str); 40 | break; 41 | case "results": 42 | const csrftoken = document.querySelector( 43 | "[name=csrfmiddlewaretoken]" 44 | ).value; 45 | let headers = { 46 | "Content-Type": "application/json;charset=UTF-8", 47 | "X-CSRFToken": csrftoken, 48 | }; 49 | 50 | result = result.concat(msg.points); 51 | 52 | if (++finished == 2) { 53 | clock.terminate(); 54 | finder1.terminate(); 55 | finder2.terminate(); 56 | let params = { 57 | points: result, 58 | }; 59 | fetch("/plot/hist/", { 60 | method: "POST", 61 | headers: headers, 62 | body: jsonify(params), 63 | credentials: "same-origin", 64 | }) 65 | .then((res) => res.blob()) 66 | .then((blob) => { 67 | document.getElementById("memoryLatencyGraph").src = 68 | URL.createObjectURL(blob); 69 | }); 70 | } 71 | default: 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/performance/memoryWorker.js: -------------------------------------------------------------------------------- 1 | // Constants 2 | const P = 4096; 3 | const KB = 1024; 4 | const MB = 1024 * 1024; 5 | //const ITERATIONS = BigInt(MB * 64); 6 | const ITERATIONS = BigInt(MB * 16); 7 | const RANDOM = true; 8 | 9 | const START = 512; 10 | 11 | self.onmessage = async function start(evt) { 12 | // Prepare wasm instance 13 | const { module, memory } = evt.data; 14 | const instance = new WebAssembly.Instance(module, { 15 | env: { mem: memory }, 16 | console: { 17 | log: function (arg) { 18 | console.log(arg); 19 | }, 20 | }, 21 | }); 22 | // Memory view 23 | const view = new DataView(memory.buffer); 24 | 25 | await new Promise((r) => setTimeout(r, 10)); // allow counter to start 26 | 27 | let points = []; 28 | prepareList(4 * MB, view); 29 | 30 | let ptr; 31 | for (let outer = 0; outer < 2; outer++) { 32 | ptr = START; 33 | for (let i = 0; i < MB; i++) { 34 | let result = instance.exports.maccess(ptr); 35 | ptr = view.getUint32(ptr, true); 36 | postMessage({ 37 | type: "progress", 38 | value: (outer * MB + i) / (MB * 2), 39 | }); 40 | if (i % 128 == 0) points.push(Number(result)); 41 | } 42 | } 43 | 44 | postMessage({ type: "progress", value: 1 }); 45 | 46 | postMessage({ type: "results", points: points }); 47 | 48 | postMessage({ type: "terminate" }); 49 | }; 50 | 51 | function prepareList(size, view) { 52 | // init [0, ... , size - 1] 53 | let indices = []; 54 | for (let i = 0; i < size; i++) { 55 | indices.push(i); 56 | } 57 | 58 | // randomize indices 59 | if (RANDOM) { 60 | for (let i = 0; i < size; i++) { 61 | let j = i + getRandomInt(0, size - i - 1); 62 | // swap 63 | if (j != i) [indices[j], indices[i]] = [indices[i], indices[j]]; 64 | } 65 | } 66 | 67 | // index to address conversion 68 | indices = indices.map((x) => START + x * 4); 69 | 70 | // write linked list to memory 71 | for (let i = 1; i < size; i++) { 72 | view.setUint32(indices[i - 1], indices[i], true); 73 | } 74 | view.setUint32(indices[size - 1], indices[0], true); 75 | } 76 | 77 | function getRandomInt(min, max) { 78 | return Math.floor(Math.random() * (max - min + 1)) + min; 79 | } 80 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/performance/performance.js: -------------------------------------------------------------------------------- 1 | async function calculatePerformance(CanvasJS) { 2 | document.getElementById("startButton").disabled = true; 3 | 4 | let points = []; 5 | 6 | let ITERATIONS = 500; 7 | let counter; 8 | let start; 9 | 10 | for (let i = 0; i < ITERATIONS; i++) { 11 | counter = 0; 12 | start = performance.now() + 1; 13 | while (start > performance.now()) { 14 | counter += 1; 15 | } 16 | 17 | points.push({ x: Number(i), y: Number(counter) }); 18 | } 19 | 20 | updateProgress(1 / 3); 21 | 22 | await new Promise((r) => setTimeout(r, 100)); 23 | 24 | for (let i = 0; i < ITERATIONS; i++) { 25 | counter = 0; 26 | start = performance.now() + 1; 27 | while (start > performance.now()) { 28 | counter += 1; 29 | } 30 | 31 | points.push({ x: Number(i + ITERATIONS), y: Number(counter) }); 32 | } 33 | 34 | updateProgress(2 / 3); 35 | 36 | await new Promise((r) => setTimeout(r, 100)); 37 | 38 | for (let i = 0; i < ITERATIONS; i++) { 39 | counter = 0; 40 | start = performance.now() + 1; 41 | while (start > performance.now()) { 42 | counter += 1; 43 | } 44 | 45 | points.push({ x: Number(i + ITERATIONS * 2), y: Number(counter) }); 46 | } 47 | 48 | updateProgress(1); 49 | var chart = new CanvasJS.Chart("chartContainer", { 50 | animationEnabled: true, 51 | theme: "light2", 52 | data: [ 53 | { 54 | type: "line", 55 | indexLabelFontSize: 16, 56 | dataPoints: points, 57 | }, 58 | ], 59 | }); 60 | chart.render(); 61 | } 62 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/performance/performanceMulti.js: -------------------------------------------------------------------------------- 1 | let WORKERS = 1; 2 | const ITERATIONS = 10000; 3 | let results = new Array(WORKERS).fill({}); 4 | let workers = []; 5 | let finishedWorkers = 0; 6 | 7 | async function calculatePerformance(CanvasJS) { 8 | document.getElementById("startButton").disabled = true; 9 | 10 | WORKERS = Number(document.forms["startForm"]["cores"].value); 11 | 12 | if (isNaN(WORKERS) || WORKERS == 0) { 13 | WORKERS = 1; 14 | } 15 | 16 | for (let i = 0; i < WORKERS; i++) { 17 | let worker = new Worker("/static/performance/performanceWorker.js"); 18 | worker.onmessage = callback; 19 | workers.push(worker); 20 | } 21 | 22 | for (let i = 0; i < WORKERS; i++) { 23 | workers[i].postMessage({ workerId: i, iterations: ITERATIONS }); 24 | } 25 | } 26 | 27 | function callback(event) { 28 | let data = event.data; 29 | workers[data.workerId].terminate(); 30 | results[data.workerId] = { 31 | type: "line", 32 | indexLabelFontSize: 16, 33 | dataPoints: data.points, 34 | }; 35 | finishedWorkers += 1; 36 | updateProgress(finishedWorkers / WORKERS); 37 | 38 | if (finishedWorkers == WORKERS) { 39 | var chart = new CanvasJS.Chart("chartContainer", { 40 | animationEnabled: true, 41 | theme: "light2", 42 | data: results, 43 | }); 44 | chart.render(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/performance/performanceWorker.js: -------------------------------------------------------------------------------- 1 | let workerId = 0; 2 | 3 | onmessage = function (event) { 4 | let data = event.data; 5 | workerId = data.workerId; 6 | 7 | benchmark(data.iterations); 8 | }; 9 | 10 | function benchmark(iterations) { 11 | let points = []; 12 | for (let i = 0; i < iterations; i++) { 13 | counter = 0; 14 | start = performance.now() + 1; 15 | while (start > performance.now()) { 16 | counter += 1; 17 | } 18 | 19 | points.push({ x: Number(i), y: Number(counter) }); 20 | } 21 | 22 | postMessage({ workerId: workerId, points: points }); 23 | } 24 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/tlb/tlbSize.js: -------------------------------------------------------------------------------- 1 | async function calculateTLBSize(CanvasJS) { 2 | document.getElementById("startButton").disabled = true; 3 | 4 | // Shared memory 5 | memory = new WebAssembly.Memory({ 6 | initial: amountOfPages, 7 | maximum: amountOfPages, 8 | shared: true, 9 | }); 10 | 11 | const clock = await startClockWorker(); 12 | 13 | const resp2 = await fetch("/static/wasm/size.wasm"); 14 | const bin2 = await resp2.arrayBuffer(); 15 | const module2 = new WebAssembly.Module(bin2); 16 | const finder = new Worker("/static/tlb/tlbsizeFinder.js"); 17 | finder.onmessage = function handle(evt) { 18 | let msg = evt.data; 19 | switch (msg.type) { 20 | case "progress": 21 | updateProgress(msg.value); 22 | break; 23 | case "log": 24 | log(...msg.str); 25 | break; 26 | case "terminate": 27 | clock.terminate(); 28 | finder.terminate(); 29 | break; 30 | 31 | case "results": 32 | var chart = new CanvasJS.Chart("chartContainer", { 33 | animationEnabled: true, 34 | theme: "light2", 35 | data: [ 36 | { 37 | type: "line", 38 | indexLabelFontSize: 16, 39 | dataPoints: msg.points, 40 | }, 41 | ], 42 | }); 43 | chart.render(); 44 | break; 45 | default: 46 | } 47 | }; 48 | finder.postMessage({ module: module2, memory: memory }); 49 | } 50 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/tlb/tlbsizeFinder.js: -------------------------------------------------------------------------------- 1 | // Constants 2 | const KB = 1024; 3 | const MB = 1024 * 1024; 4 | const MAXSIZE = 128; 5 | const RANDOM = false; 6 | const ITERATIONS = 32 * MB; 7 | const PAGESIZE = 4096; 8 | const START = 512; 9 | 10 | self.onmessage = async function start(evt) { 11 | // Prepare wasm instance 12 | const { module, memory } = evt.data; 13 | const instance = new WebAssembly.Instance(module, { 14 | env: { mem: memory }, 15 | console: { 16 | log: function (arg) { 17 | console.log(arg); 18 | }, 19 | }, 20 | }); 21 | 22 | const view = new DataView(memory.buffer); 23 | 24 | await new Promise((r) => setTimeout(r, 10)); // allow counter to start 25 | 26 | let points = []; 27 | 28 | for (let size = 2; size < MAXSIZE; size += 4) { 29 | prepareList(size, view); 30 | 31 | let time = instance.exports.iterate(START, BigInt(ITERATIONS)); 32 | 33 | postMessage({ type: "progress", value: size / MAXSIZE }); 34 | points.push({ x: Number(size), y: Number(time) }); 35 | } 36 | 37 | postMessage({ type: "progress", value: 1 }); 38 | 39 | postMessage({ type: "results", points: points }); 40 | 41 | postMessage({ type: "terminate" }); 42 | }; 43 | 44 | function prepareList(size, view) { 45 | let indices = []; 46 | for (let i = 0; i < size; i++) { 47 | indices.push(i * PAGESIZE); 48 | } 49 | 50 | // randomize indices 51 | if (RANDOM) { 52 | for (let i = 0; i < size; i++) { 53 | let j = i + getRandomInt(0, size - i - 1); 54 | // swap 55 | if (j != i) [indices[j], indices[i]] = [indices[i], indices[j]]; 56 | } 57 | } 58 | 59 | indices = indices.map((x) => START + x); 60 | 61 | // write linked list to memory 62 | for (let i = 1; i < size; i++) { 63 | view.setUint32(indices[i - 1], indices[i], true); 64 | } 65 | view.setUint32(indices[size - 1], indices[0], true); 66 | } 67 | 68 | function getRandomInt(min, max) { 69 | return Math.floor(Math.random() * (max - min + 1)) + min; 70 | } 71 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/utils/clockWorker.js: -------------------------------------------------------------------------------- 1 | self.onmessage = function (evt) { 2 | const { module, memory } = evt.data; 3 | const instance = new WebAssembly.Instance(module, { env: { mem: memory } }); 4 | }; 5 | -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/bits.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/wasm/bits.wasm -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/clock.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/wasm/clock.wasm -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/clock.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (import "env" "mem" (memory 1024 1024 shared)) 3 | (func $main 4 | (loop $ccc 5 | ;;(i64.atomic.rmw.add (i32.const 256) (i64.const 1)) 6 | (i64.store (i32.const 256) (i64.add (i64.load (i32.const 256)) (i64.const 1))) 7 | (br $ccc)) 8 | ) 9 | (start $main) 10 | ) -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/loadbuffer.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/wasm/loadbuffer.wasm -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/loadbuffer.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (import "env" "mem" (memory 1024 1024 shared)) 3 | (import "console" "log" (func $log (param i32))) 4 | (export "routine" (func $routine)) 5 | 6 | (func $routine (param $p1 i32) (param $p2 i32) (param $iterations i32) (result i64) 7 | (local $t0 i64) 8 | (local $tmp i32) 9 | 10 | (local.set $t0 (i64.load (i32.const 256))) 11 | 12 | ;; actual routine 13 | (loop $iter 14 | 15 | ;; cache miss 16 | (local.set $p1 (i32.load (local.get $p1))) 17 | 18 | (i32.const 0) 19 | ;; split here 20 | (i32.add (i32.load (i32.const 0))) 21 | (i32.add (i32.load (i32.const 0))) 22 | (i32.add (i32.load (i32.const 0))) 23 | (i32.add (i32.load (i32.const 0))) 24 | (i32.add (i32.load (i32.const 0))) 25 | (i32.add (i32.load (i32.const 0))) 26 | (i32.add (i32.load (i32.const 0))) 27 | (i32.add (i32.load (i32.const 0))) 28 | (i32.add (i32.load (i32.const 0))) 29 | (i32.add (i32.load (i32.const 0))) 30 | (i32.add (i32.load (i32.const 0))) 31 | (i32.add (i32.load (i32.const 0))) 32 | (i32.add (i32.load (i32.const 0))) 33 | (i32.add (i32.load (i32.const 0))) 34 | (i32.add (i32.load (i32.const 0))) 35 | (i32.add (i32.load (i32.const 0))) 36 | 37 | ;; cache miss 38 | (local.set $p2 (i32.load (local.get $p2))) 39 | 40 | (local.set $tmp) 41 | (i32.const 0) 42 | 43 | ;; split here 44 | (i32.add (i32.load (i32.const 0))) 45 | (i32.add (i32.load (i32.const 0))) 46 | (i32.add (i32.load (i32.const 0))) 47 | (i32.add (i32.load (i32.const 0))) 48 | (i32.add (i32.load (i32.const 0))) 49 | (i32.add (i32.load (i32.const 0))) 50 | (i32.add (i32.load (i32.const 0))) 51 | (i32.add (i32.load (i32.const 0))) 52 | (i32.add (i32.load (i32.const 0))) 53 | (i32.add (i32.load (i32.const 0))) 54 | (i32.add (i32.load (i32.const 0))) 55 | (i32.add (i32.load (i32.const 0))) 56 | (i32.add (i32.load (i32.const 0))) 57 | (i32.add (i32.load (i32.const 0))) 58 | (i32.add (i32.load (i32.const 0))) 59 | (i32.add (i32.load (i32.const 0))) 60 | 61 | (local.set $tmp) 62 | 63 | (local.set $iterations (i32.sub (local.get $iterations) (i32.const 1))) 64 | (br_if $iter (i32.gt_u (local.get $iterations) (i32.const 0))) 65 | ) 66 | 67 | (i64.load (i32.const 256)) 68 | (local.get $t0) 69 | (i64.sub) 70 | 71 | return 72 | ) 73 | ) -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/pagesize.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/wasm/pagesize.wasm -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/pagesize.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (import "env" "mem" (memory 1024 1024 shared)) 3 | (import "console" "log" (func $log (param i32))) 4 | (export "maccess" (func $maccess)) 5 | (export "write" (func $write)) 6 | 7 | (func $maccess (param $ptr i32) (result i64) 8 | (local $t0 i64) 9 | (local $tmp i32) 10 | 11 | (local.set $t0 (i64.load (i32.const 256))) 12 | 13 | (local.set $tmp (i32.load (local.get $ptr))) 14 | 15 | (i64.load (i32.const 256)) 16 | (local.get $t0) 17 | (i64.sub) 18 | 19 | return 20 | ) 21 | 22 | (func $write (param $ptr i32) (param $value i32) 23 | 24 | (i32.store (local.get $ptr) (local.get $value)) 25 | 26 | return 27 | ) 28 | ) -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/prefetch.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/wasm/prefetch.wasm -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/prefetch.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (import "env" "mem" (memory 1024 1024 shared)) 3 | (import "console" "log" (func $log (param i32))) 4 | (export "maccess" (func $maccess)) 5 | (export "write" (func $write)) 6 | 7 | (func $maccess (param $ptr i32) (param $offset i32) (param $fence i32) (result i64) 8 | (local $t0 i64) 9 | (local $tmp i32) 10 | 11 | (local.set $tmp (i32.load (local.get $ptr))) 12 | 13 | ;; fence 14 | (loop $iter 15 | (local.set $fence (i32.sub (local.get $fence) (i32.const 1))) 16 | (br_if $iter (i32.gt_u (local.get $fence) (i32.const 0))) 17 | ) 18 | 19 | ;; start 20 | (local.set $t0 (i64.load (i32.const 256))) 21 | 22 | (local.set $tmp (i32.load (i32.add (local.get $ptr) (local.get $offset)))) 23 | 24 | ;; time 25 | (i64.load (i32.const 256)) 26 | (local.get $t0) 27 | (i64.sub) 28 | 29 | return 30 | ) 31 | 32 | (func $write (param $ptr i32) (param $value i32) 33 | 34 | (i32.store (local.get $ptr) (local.get $value)) 35 | 36 | return 37 | ) 38 | ) -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/size.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/cpuprofiler/static/wasm/size.wasm -------------------------------------------------------------------------------- /web/cpuprofiler/static/wasm/size.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (import "env" "mem" (memory 1024 1024 shared)) 3 | (import "console" "log" (func $log (param i32))) 4 | (export "iterate" (func $iterate)) 5 | (export "check" (func $check)) 6 | (export "write" (func $write)) 7 | 8 | (func $iterate (param $start i32) (param $iterations i64) (result i64) 9 | (local $head i32) 10 | (local $i i64) 11 | (local $t0 i64) 12 | (local.set $i (i64.const 1)) 13 | (local.set $head (local.get $start)) 14 | 15 | (local.set $t0 (i64.load (i32.const 256))) 16 | 17 | (loop $iter 18 | (local.set $head (i32.load (local.get $head))) 19 | (local.set $i (i64.add (local.get $i) (i64.const 1))) 20 | (br_if $iter (i64.lt_u (local.get $i) (local.get $iterations))) 21 | ) 22 | 23 | (i64.load (i32.const 256)) 24 | (local.get $t0) 25 | (i64.sub) 26 | 27 | return 28 | ) 29 | 30 | (func $check (param $start i32) (result i64) 31 | (local $head i32) 32 | (local $i i64) 33 | (local.set $i (i64.const 0)) 34 | (local.set $head (local.get $start)) 35 | 36 | (loop $iter 37 | ;; (local.get $head) 38 | ;; (call $log) 39 | (local.set $head (i32.load (local.get $head))) 40 | (local.set $i (i64.add (local.get $i) (i64.const 1))) 41 | (br_if $iter (i32.ne (local.get $head) (local.get $start))) 42 | ) 43 | 44 | (local.get $i) 45 | return 46 | ) 47 | 48 | (func $write (param $ptr i32) (param $value i32) 49 | 50 | (i32.store (local.get $ptr) (local.get $value)) 51 | 52 | return 53 | ) 54 | ) -------------------------------------------------------------------------------- /web/cpuprofiler/urls.py: -------------------------------------------------------------------------------- 1 | """cpuprofiler URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.2/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import include, path 18 | from django.conf import settings 19 | from django.conf.urls.static import static 20 | 21 | urlpatterns = [ 22 | path('plot/', include('plot.urls')), 23 | path('', include('navigation.urls')), 24 | path('', include('profilers.urls')), 25 | path('', include('upload.urls')), 26 | path('admin/', admin.site.urls), 27 | ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) 28 | -------------------------------------------------------------------------------- /web/cpuprofiler/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for cpuprofiler project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cpuprofiler.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /web/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'cpuprofiler.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /web/navigation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/navigation/__init__.py -------------------------------------------------------------------------------- /web/navigation/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /web/navigation/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class NavigationConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'navigation' 7 | -------------------------------------------------------------------------------- /web/navigation/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/navigation/migrations/__init__.py -------------------------------------------------------------------------------- /web/navigation/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /web/navigation/templates/overview.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | 4 | {% block content %} 5 | 13 |

14 | Here is a list of each individual benchmark we are running. You can inspect 15 | and run each benchmark on its own. There will be a few explanations here and 16 | there, that are written for interested computer scientists. 17 |

18 |
22 | 31 |
32 |
33 | 68 |
69 | {% endblock %} 70 | -------------------------------------------------------------------------------- /web/navigation/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /web/navigation/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from django.conf import settings 3 | from django.conf.urls.static import static 4 | 5 | from . import views 6 | 7 | urlpatterns = [ 8 | path('', views.landing, name='landing'), 9 | path('start/', views.start, name='start'), 10 | path('overview/', views.overview, name='overview'), 11 | path('problem/', views.problem, name='problem'), 12 | ] -------------------------------------------------------------------------------- /web/navigation/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib import messages 2 | #from django.core.checks import messages 3 | from django.shortcuts import render, reverse, redirect 4 | from django.http import HttpResponse 5 | 6 | 7 | def landing(request): 8 | return render(request, 'landing.html') 9 | 10 | 11 | def start(request): 12 | return render(request, 'home.html') 13 | 14 | 15 | def problem(request): 16 | return render(request, 'problem.html') 17 | 18 | 19 | def overview(request): 20 | return render(request, 'overview.html') -------------------------------------------------------------------------------- /web/plot/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/plot/__init__.py -------------------------------------------------------------------------------- /web/plot/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /web/plot/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PlotConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'plot' 7 | -------------------------------------------------------------------------------- /web/plot/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/plot/migrations/__init__.py -------------------------------------------------------------------------------- /web/plot/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /web/plot/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /web/plot/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from django.conf import settings 3 | from django.conf.urls.static import static 4 | 5 | from . import views 6 | 7 | urlpatterns = [ 8 | path('line/', views.line, name='line'), 9 | path('bar/', views.bar, name='bar'), 10 | path('multiline/', views.multiline, name='multiline'), 11 | path('hist/', views.hist, name='hist'), 12 | ] -------------------------------------------------------------------------------- /web/plot/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http import HttpResponse 3 | from django.views.decorators.http import require_http_methods 4 | import json 5 | import matplotlib 6 | import base64 7 | import matplotlib.pyplot as plt 8 | import numpy as np 9 | 10 | 11 | @require_http_methods(["POST"]) 12 | def line(request): 13 | response = HttpResponse() 14 | 15 | body_unicode = request.body.decode('utf-8') 16 | body = json.loads(body_unicode) 17 | points = body.get('points', list()) 18 | 19 | fig = matplotlib.figure.Figure() 20 | ax = fig.add_subplot(1,1,1) 21 | x_vals = [] 22 | y_vals = [] 23 | 24 | for d in points: 25 | x_vals.append(d["x"]) 26 | y_vals.append(d["y"]) 27 | 28 | ax.plot(x_vals, y_vals) 29 | ax.grid(axis='x', color='0.95') 30 | ax.set(xlabel='', ylabel='time') 31 | 32 | fig.savefig(response) 33 | return response 34 | 35 | 36 | @require_http_methods(["POST"]) 37 | def hist(request): 38 | response = HttpResponse() 39 | 40 | body_unicode = request.body.decode('utf-8') 41 | body = json.loads(body_unicode) 42 | points = body.get('points', list()) 43 | 44 | fig = matplotlib.figure.Figure() 45 | ax = fig.add_subplot(1,1,1) 46 | x_vals = [] 47 | y_vals = [] 48 | 49 | # ax.set_ylim(0, 1000) 50 | # ax.hist(points, range=(0, 300), bins=300) 51 | ax.hist(points, bins=np.arange(min(points), max(points) + 1, 1)) 52 | ax.set(xlabel='time', ylabel='') 53 | ax.grid(axis='x', color='red', alpha=0.2) 54 | 55 | fig.savefig(response) 56 | return response 57 | 58 | 59 | @require_http_methods(["POST"]) 60 | def multiline(request): 61 | response = HttpResponse() 62 | 63 | body_unicode = request.body.decode('utf-8') 64 | body = json.loads(body_unicode) 65 | points = body.get('points', list()) 66 | 67 | fig = matplotlib.figure.Figure() 68 | ax = fig.add_subplot(1,1,1) 69 | 70 | for line in points: 71 | x_vals = [] 72 | y_vals = [] 73 | 74 | for d in line: 75 | x_vals.append(d["x"]) 76 | y_vals.append(d["y"]) 77 | 78 | ax.plot(x_vals, y_vals) 79 | 80 | ax.grid(axis='x', color='0.95') 81 | ax.set(xlabel='', ylabel='time') 82 | 83 | fig.savefig(response) 84 | return response 85 | 86 | 87 | @require_http_methods(["POST"]) 88 | def bar(request): 89 | response = HttpResponse() 90 | 91 | body_unicode = request.body.decode('utf-8') 92 | body = json.loads(body_unicode) 93 | points = body.get('points', list()) 94 | 95 | fig = matplotlib.figure.Figure() 96 | ax = fig.add_subplot(1,1,1) 97 | x_vals = [] 98 | y_vals = [] 99 | 100 | for d in points: 101 | x_vals.append(d["label"]) 102 | y_vals.append(d["y"]) 103 | 104 | ax.bar(x_vals, y_vals) 105 | ax.set(xlabel='', ylabel='time') 106 | 107 | fig.savefig(response) 108 | return response -------------------------------------------------------------------------------- /web/profilers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/profilers/__init__.py -------------------------------------------------------------------------------- /web/profilers/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | -------------------------------------------------------------------------------- /web/profilers/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ProfilersConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'profilers' 7 | -------------------------------------------------------------------------------- /web/profilers/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/profilers/migrations/__init__.py -------------------------------------------------------------------------------- /web/profilers/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /web/profilers/templates/buffer/load.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} Load Buffer Size {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | 10 | {% endblock %} 11 | 12 | 13 | {% block text %} 14 | This benchmark will aim to reveal information about the data 15 | cache. In 16 | particular we are interested in the number of cache levels and the size of each 17 | level. Here we measure the time it takes to perform a randomized 18 | pointer chase of a 19 | fixed length. Each iteration the amount of memory the pointer chase iterates 20 | over is increased. When a cache level is satisfied, we expect a higher execution 21 | time the following iterations. An implementation of the same algorithm is 22 | explained in more detail 23 | here. 24 | 25 | {% endblock %} 26 | 27 | 28 | {% block buttons %} 29 | 37 | {% endblock %} 38 | 39 | 40 | {% block interpretation %} 41 |
How to interpret these results.
42 |

43 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere, reiciendis 44 | alias quis voluptas, accusamus recusandae quisquam ullam tenetur debitis 45 | fugiat nesciunt deleniti enim sunt necessitatibus repellat quaerat expedita 46 | officia itaque, asperiores dolores optio suscipit. Officiis, voluptates 47 | reprehenderit est voluptas unde molestias a, rerum veritatis iusto similique 48 | sequi praesentium, dolorem aut enim voluptatem pariatur corrupti quam adipisci 49 | laboriosam explicabo exercitationem nesciunt? Quas corporis animi, mollitia, 50 | odio quaerat error incidunt libero molestiae ipsum harum dolorem quibusdam 51 | accusantium amet. Facilis, officiis quia exercitationem laborum dolor ab, 52 | suscipit minima consequuntur perferendis ut at? Corrupti dicta ipsum eligendi 53 | hic modi impedit aliquam error quia ipsam. 54 |

55 | {% endblock %} 56 | 57 | 58 | {% block sourcecode %} 59 |

60 | The source code of this benchmark can be viewed 61 | here (JS), 62 | here (JS) and 63 | here (WASM) 64 |

65 | {% endblock %} 66 | -------------------------------------------------------------------------------- /web/profilers/templates/buffer/store.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} Store Buffer Size {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | 10 | {% endblock %} 11 | 12 | {% block text %} Here we will determine the size of the store buffer. {% endblock %} 13 | 14 | {% block buttons %} 15 | 23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /web/profilers/templates/cache/associativity.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} L1D Associativity {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | {% endblock %} 10 | 11 | 12 | {% block text %} 13 | This benchmark will aim to reveal information about the data 14 | cache. In 15 | particular we are interested in the number of cache levels and the size of each 16 | level. Here we measure the time it takes to perform a randomized 17 | pointer chase of a 18 | fixed length. Each iteration the amount of memory the pointer chase iterates 19 | over is increased. When a cache level is satisfied, we expect a higher execution 20 | time the following iterations. An implementation of the same algorithm is 21 | explained in more detail 22 | here. 23 | 24 | {% endblock %} 25 | 26 | {% block buttons %} 27 | 35 | {% endblock %} 36 | 37 | 38 | {% block interpretation %} 39 |
How to interpret these results.
40 |

41 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere, reiciendis 42 | alias quis voluptas, accusamus recusandae quisquam ullam tenetur debitis 43 | fugiat nesciunt deleniti enim sunt necessitatibus repellat quaerat expedita 44 | officia itaque, asperiores dolores optio suscipit. Officiis, voluptates 45 | reprehenderit est voluptas unde molestias a, rerum veritatis iusto similique 46 | sequi praesentium, dolorem aut enim voluptatem pariatur corrupti quam adipisci 47 | laboriosam explicabo exercitationem nesciunt? Quas corporis animi, mollitia, 48 | odio quaerat error incidunt libero molestiae ipsum harum dolorem quibusdam 49 | accusantium amet. Facilis, officiis quia exercitationem laborum dolor ab, 50 | suscipit minima consequuntur perferendis ut at? Corrupti dicta ipsum eligendi 51 | hic modi impedit aliquam error quia ipsam. 52 |

53 | {% endblock %} 54 | 55 | 56 | {% block sourcecode %} 57 |

58 | The source code of this benchmark can be viewed 59 | here (JS) and 60 | here (WASM) 61 |

62 | {% endblock %} 63 | -------------------------------------------------------------------------------- /web/profilers/templates/misc/bits.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} 32-bit vs 64-bit {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | {% endblock %} 10 | 11 | {% block text %} Here we will determine the presence of 32-bit vs 64-bit. {% endblock %} 12 | 13 | {% block buttons %} 14 | 22 | {% endblock %} 23 | -------------------------------------------------------------------------------- /web/profilers/templates/misc/cores.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} Number of Cores {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | {% endblock %} 10 | 11 | 12 | {% block text %} 13 | This benchmark will aim to reveal information about the data 14 | cache. In 15 | particular we are interested in the number of cache levels and the size of each 16 | level. Here we measure the time it takes to perform a randomized 17 | pointer chase of a 18 | fixed length. Each iteration the amount of memory the pointer chase iterates 19 | over is increased. When a cache level is satisfied, we expect a higher execution 20 | time the following iterations. An implementation of the same algorithm is 21 | explained in more detail 22 | here. 23 | 24 | {% endblock %} 25 | 26 | 27 | 28 | {% block buttons %} 29 | 37 | {% endblock %} 38 | 39 | 40 | {% block interpretation %} 41 |
How to interpret these results.
42 |

43 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere, reiciendis 44 | alias quis voluptas, accusamus recusandae quisquam ullam tenetur debitis 45 | fugiat nesciunt deleniti enim sunt necessitatibus repellat quaerat expedita 46 | officia itaque, asperiores dolores optio suscipit. Officiis, voluptates 47 | reprehenderit est voluptas unde molestias a, rerum veritatis iusto similique 48 | sequi praesentium, dolorem aut enim voluptatem pariatur corrupti quam adipisci 49 | laboriosam explicabo exercitationem nesciunt? Quas corporis animi, mollitia, 50 | odio quaerat error incidunt libero molestiae ipsum harum dolorem quibusdam 51 | accusantium amet. Facilis, officiis quia exercitationem laborum dolor ab, 52 | suscipit minima consequuntur perferendis ut at? Corrupti dicta ipsum eligendi 53 | hic modi impedit aliquam error quia ipsam. 54 |

55 | {% endblock %} 56 | 57 | 58 | {% block sourcecode %} 59 |

60 | The source code of this benchmark can be viewed 61 | here (JS) and 62 | here (JS). 63 |

64 | {% endblock %} 65 | -------------------------------------------------------------------------------- /web/profilers/templates/misc/pagesize.html: -------------------------------------------------------------------------------- 1 | {% extends "profiler.html" %} 2 | 3 | 4 | {% block headline %} Pagesize {% endblock %} 5 | 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | {% endblock %} 10 | 11 | 12 | {% block text %} 13 | This benchmark will aim to reveal information about the data 14 | cache. In 15 | particular we are interested in the number of cache levels and the size of each 16 | level. Here we measure the time it takes to perform a randomized 17 | pointer chase of a 18 | fixed length. Each iteration the amount of memory the pointer chase iterates 19 | over is increased. When a cache level is satisfied, we expect a higher execution 20 | time the following iterations. An implementation of the same algorithm is 21 | explained in more detail 22 | here. 23 | 24 | {% endblock %} 25 | 26 | {% block buttons %} 27 | 35 | {% endblock %} 36 | 37 | 38 | {% block interpretation %} 39 |
How to interpret these results.
40 |

41 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere, reiciendis 42 | alias quis voluptas, accusamus recusandae quisquam ullam tenetur debitis 43 | fugiat nesciunt deleniti enim sunt necessitatibus repellat quaerat expedita 44 | officia itaque, asperiores dolores optio suscipit. Officiis, voluptates 45 | reprehenderit est voluptas unde molestias a, rerum veritatis iusto similique 46 | sequi praesentium, dolorem aut enim voluptatem pariatur corrupti quam adipisci 47 | laboriosam explicabo exercitationem nesciunt? Quas corporis animi, mollitia, 48 | odio quaerat error incidunt libero molestiae ipsum harum dolorem quibusdam 49 | accusantium amet. Facilis, officiis quia exercitationem laborum dolor ab, 50 | suscipit minima consequuntur perferendis ut at? Corrupti dicta ipsum eligendi 51 | hic modi impedit aliquam error quia ipsam. 52 |

53 | {% endblock %} 54 | 55 | 56 | {% block sourcecode %} 57 |

58 | The source code of this benchmark can be viewed 59 | here (JS) and 60 | here (WASM). 61 |

62 | {% endblock %} 63 | -------------------------------------------------------------------------------- /web/profilers/templates/misc/prefetcher.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} Prefetcher Presence {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | {% endblock %} 10 | 11 | 12 | {% block text %} 13 | This benchmark will aim to reveal information about the data 14 | cache. In 15 | particular we are interested in the number of cache levels and the size of each 16 | level. Here we measure the time it takes to perform a randomized 17 | pointer chase of a 18 | fixed length. Each iteration the amount of memory the pointer chase iterates 19 | over is increased. When a cache level is satisfied, we expect a higher execution 20 | time the following iterations. An implementation of the same algorithm is 21 | explained in more detail 22 | here. 23 | 24 | {% endblock %} 25 | 26 | {% block buttons %} 27 | 35 | {% endblock %} 36 | 37 | 38 | {% block interpretation %} 39 |
How to interpret these results.
40 |

41 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere, reiciendis 42 | alias quis voluptas, accusamus recusandae quisquam ullam tenetur debitis 43 | fugiat nesciunt deleniti enim sunt necessitatibus repellat quaerat expedita 44 | officia itaque, asperiores dolores optio suscipit. Officiis, voluptates 45 | reprehenderit est voluptas unde molestias a, rerum veritatis iusto similique 46 | sequi praesentium, dolorem aut enim voluptatem pariatur corrupti quam adipisci 47 | laboriosam explicabo exercitationem nesciunt? Quas corporis animi, mollitia, 48 | odio quaerat error incidunt libero molestiae ipsum harum dolorem quibusdam 49 | accusantium amet. Facilis, officiis quia exercitationem laborum dolor ab, 50 | suscipit minima consequuntur perferendis ut at? Corrupti dicta ipsum eligendi 51 | hic modi impedit aliquam error quia ipsam. 52 |

53 | {% endblock %} 54 | 55 | 56 | {% block sourcecode %} 57 |

58 | The source code of this benchmark can be viewed 59 | here (JS) and 60 | here (WASM). 61 |

62 | {% endblock %} 63 | -------------------------------------------------------------------------------- /web/profilers/templates/misc/timer.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} Timer Precision {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | {% endblock %} 10 | 11 | 12 | {% block text %} 13 | This benchmark will aim to reveal information about the data 14 | cache. In 15 | particular we are interested in the number of cache levels and the size of each 16 | level. Here we measure the time it takes to perform a randomized 17 | pointer chase of a 18 | fixed length. Each iteration the amount of memory the pointer chase iterates 19 | over is increased. When a cache level is satisfied, we expect a higher execution 20 | time the following iterations. An implementation of the same algorithm is 21 | explained in more detail 22 | here. 23 | 24 | {% endblock %} 25 | 26 | 27 | {% block buttons %} 28 | 36 | {% endblock %} 37 | 38 | 39 | {% block interpretation %} 40 |
How to interpret these results.
41 |

42 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Magni, inventore 43 | velit adipisci accusamus consequatur numquam porro totam, eius dolor iure 44 | repudiandae. Totam perspiciatis, nulla accusamus officia fugit rem natus 45 | ipsam. 46 |

47 | {% endblock %} 48 | 49 | 50 | {% block sourcecode %} 51 |

52 | The source code of this benchmark can be viewed 53 | here (JS). 54 |

55 | {% endblock %} 56 | -------------------------------------------------------------------------------- /web/profilers/templates/performance/memory.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} Memory Latencies {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | {% endblock %} 10 | 11 | 12 | {% block text %} 13 | This benchmark will aim to reveal information about the data 14 | cache. In 15 | particular we are interested in the number of cache levels and the size of each 16 | level. Here we measure the time it takes to perform a randomized 17 | pointer chase of a 18 | fixed length. Each iteration the amount of memory the pointer chase iterates 19 | over is increased. When a cache level is satisfied, we expect a higher execution 20 | time the following iterations. An implementation of the same algorithm is 21 | explained in more detail 22 | here. 23 | 24 | {% endblock %} 25 | 26 | 27 | {% block buttons %} 28 | 36 | {% endblock %} {% block charts %} {% csrf_token %} 37 | 38 | 42 | 43 | {% endblock %} 44 | 45 | 46 | {% block interpretation %} 47 |
How to interpret these results.
48 |

49 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere, reiciendis 50 | alias quis voluptas, accusamus recusandae quisquam ullam tenetur debitis 51 | fugiat nesciunt deleniti enim sunt necessitatibus repellat quaerat expedita 52 | officia itaque, asperiores dolores optio suscipit. Officiis, voluptates 53 | reprehenderit est voluptas unde molestias a, rerum veritatis iusto similique 54 | sequi praesentium, dolorem aut enim voluptatem pariatur corrupti quam adipisci 55 | laboriosam explicabo exercitationem nesciunt? Quas corporis animi, mollitia, 56 | odio quaerat error incidunt libero molestiae ipsum harum dolorem quibusdam 57 | accusantium amet. Facilis, officiis quia exercitationem laborum dolor ab, 58 | suscipit minima consequuntur perferendis ut at? Corrupti dicta ipsum eligendi 59 | hic modi impedit aliquam error quia ipsam. 60 |

61 | {% endblock %} 62 | 63 | 64 | {% block sourcecode %} 65 |

66 | The source code of this benchmark can be viewed 67 | here (JS) and 68 | here (WASM) 69 |

70 | {% endblock %} 71 | -------------------------------------------------------------------------------- /web/profilers/templates/performance/multi.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} Multi-Core Performance {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | {% endblock %} 10 | 11 | 12 | {% block text %} 13 | This benchmark will aim to reveal information about the data 14 | cache. In 15 | particular we are interested in the number of cache levels and the size of each 16 | level. Here we measure the time it takes to perform a randomized 17 | pointer chase of a 18 | fixed length. Each iteration the amount of memory the pointer chase iterates 19 | over is increased. When a cache level is satisfied, we expect a higher execution 20 | time the following iterations. An implementation of the same algorithm is 21 | explained in more detail 22 | here. 23 | 24 | {% endblock %} 25 | 26 | 27 | {% block buttons %} 28 |
29 |
30 | 39 | 47 |
48 |
49 | {% endblock %} 50 | 51 | 52 | {% block interpretation %} 53 |
How to interpret these results.
54 |

55 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere, reiciendis 56 | alias quis voluptas, accusamus recusandae quisquam ullam tenetur debitis 57 | fugiat nesciunt deleniti enim sunt necessitatibus repellat quaerat expedita 58 | officia itaque, asperiores dolores optio suscipit. Officiis, voluptates 59 | reprehenderit est voluptas unde molestias a, rerum veritatis iusto similique 60 | sequi praesentium, dolorem aut enim voluptatem pariatur corrupti quam adipisci 61 | laboriosam explicabo exercitationem nesciunt? Quas corporis animi, mollitia, 62 | odio quaerat error incidunt libero molestiae ipsum harum dolorem quibusdam 63 | accusantium amet. Facilis, officiis quia exercitationem laborum dolor ab, 64 | suscipit minima consequuntur perferendis ut at? Corrupti dicta ipsum eligendi 65 | hic modi impedit aliquam error quia ipsam. 66 |

67 | {% endblock %} 68 | 69 | 70 | {% block sourcecode %} 71 |

72 | The source code of this benchmark can be viewed 73 | here (JS) and 74 | here (JS). 75 |

76 | {% endblock %} 77 | -------------------------------------------------------------------------------- /web/profilers/templates/performance/single.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {% extends "profiler.html" %} 4 | 5 | {% block headline %} Single-Core Performance {% endblock %} 6 | 7 | {% block scripts %} {% load static %} 8 | 9 | {% endblock %} 10 | 11 | 12 | {% block text %} 13 | This benchmark will aim to reveal information about the data 14 | cache. In 15 | particular we are interested in the number of cache levels and the size of each 16 | level. Here we measure the time it takes to perform a randomized 17 | pointer chase of a 18 | fixed length. Each iteration the amount of memory the pointer chase iterates 19 | over is increased. When a cache level is satisfied, we expect a higher execution 20 | time the following iterations. An implementation of the same algorithm is 21 | explained in more detail 22 | here. 23 | 24 | {% endblock %} 25 | 26 | 27 | {% block buttons %} 28 | 36 | {% endblock %} 37 | 38 | 39 | {% block interpretation %} 40 |
How to interpret these results.
41 |

42 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere, reiciendis 43 | alias quis voluptas, accusamus recusandae quisquam ullam tenetur debitis 44 | fugiat nesciunt deleniti enim sunt necessitatibus repellat quaerat expedita 45 | officia itaque, asperiores dolores optio suscipit. Officiis, voluptates 46 | reprehenderit est voluptas unde molestias a, rerum veritatis iusto similique 47 | sequi praesentium, dolorem aut enim voluptatem pariatur corrupti quam adipisci 48 | laboriosam explicabo exercitationem nesciunt? Quas corporis animi, mollitia, 49 | odio quaerat error incidunt libero molestiae ipsum harum dolorem quibusdam 50 | accusantium amet. Facilis, officiis quia exercitationem laborum dolor ab, 51 | suscipit minima consequuntur perferendis ut at? Corrupti dicta ipsum eligendi 52 | hic modi impedit aliquam error quia ipsam. 53 |

54 | {% endblock %} 55 | 56 | 57 | {% block sourcecode %} 58 |

59 | The source code of this benchmark can be viewed 60 | here (JS). 61 |

62 | {% endblock %} 63 | -------------------------------------------------------------------------------- /web/profilers/templates/profiler.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} {% block nav %} 2 | 33 | {% endblock %} {% block content %} {% load static %} 34 | 35 | {% block scripts %}{% endblock %} 36 | 37 |

38 | {% block headline %}{% endblock %} 39 |

40 | 41 |

{% block text %}{% endblock %}

42 | 43 |
44 | {% block buttons %}{% endblock %} 45 |
46 | 47 |
48 |
49 |
50 |
59 |
60 |
61 | {% block charts %} 62 |
66 | {% endblock %} 67 |
68 |
69 | 70 |
{% block interpretation %}{% endblock %}
71 | 72 | {% block sourcecode %}{% endblock %} {% endblock %} 73 | -------------------------------------------------------------------------------- /web/profilers/templates/tlb/size.html: -------------------------------------------------------------------------------- 1 | 2 | {% extends "profiler.html" %} 3 | 4 | {% block headline %} TLB Size {% endblock %} 5 | 6 | {% block scripts %} {% load static %} 7 | 8 | {% endblock %} 9 | 10 | 11 | {% block text %} 12 | This benchmark will aim to reveal information about the data 13 | cache. In 14 | particular we are interested in the number of cache levels and the size of each 15 | level. Here we measure the time it takes to perform a randomized 16 | pointer chase of a 17 | fixed length. Each iteration the amount of memory the pointer chase iterates 18 | over is increased. When a cache level is satisfied, we expect a higher execution 19 | time the following iterations. An implementation of the same algorithm is 20 | explained in more detail 21 | here. 22 | 23 | {% endblock %} 24 | 25 | 26 | {% block buttons %} 27 | 35 | {% endblock %} 36 | 37 | 38 | {% block interpretation %} 39 |
How to interpret these results.
40 |

41 | Lorem ipsum dolor sit amet consectetur adipisicing elit. Facere, reiciendis 42 | alias quis voluptas, accusamus recusandae quisquam ullam tenetur debitis 43 | fugiat nesciunt deleniti enim sunt necessitatibus repellat quaerat expedita 44 | officia itaque, asperiores dolores optio suscipit. Officiis, voluptates 45 | reprehenderit est voluptas unde molestias a, rerum veritatis iusto similique 46 | sequi praesentium, dolorem aut enim voluptatem pariatur corrupti quam adipisci 47 | laboriosam explicabo exercitationem nesciunt? Quas corporis animi, mollitia, 48 | odio quaerat error incidunt libero molestiae ipsum harum dolorem quibusdam 49 | accusantium amet. Facilis, officiis quia exercitationem laborum dolor ab, 50 | suscipit minima consequuntur perferendis ut at? Corrupti dicta ipsum eligendi 51 | hic modi impedit aliquam error quia ipsam. 52 |

53 | {% endblock %} 54 | 55 | 56 | {% block sourcecode %} 57 |

58 | The source code of this benchmark can be viewed 59 | here (JS) and 60 | here (WASM) 61 |

62 | {% endblock %} 63 | -------------------------------------------------------------------------------- /web/profilers/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /web/profilers/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from django.conf import settings 3 | from django.conf.urls.static import static 4 | 5 | from . import views 6 | 7 | urlpatterns = [ 8 | path('cache/size', views.cacheSize, name='cacheSize'), 9 | path('cache/associativity', views.cacheAssociativity, name='cacheAssociativity'), 10 | path('tlb/size', views.tlbSize, name='tlbSize'), 11 | path('misc/cores', views.miscCores, name='miscCores'), 12 | path('misc/bits', views.miscBits, name='miscBits'), 13 | path('misc/pagesize', views.miscPagesize, name='miscPagesize'), 14 | path('misc/prefetcher', views.miscPrefetcher, name='miscPrefetcher'), 15 | path('timer/', views.timerPrecision, name='timerPrecision'), 16 | path('performance/single', views.performanceSingle, name='performanceSingle'), 17 | path('performance/multi', views.performanceMulti, name='performanceMulti'), 18 | path('performance/memory', views.performanceMemory, name='performanceMemory'), 19 | path('buffer/load', views.bufferLoad, name='bufferLoad'), 20 | path('buffer/store', views.bufferStore, name='bufferStore'), 21 | ] -------------------------------------------------------------------------------- /web/profilers/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib import messages 2 | #from django.core.checks import messages 3 | from django.shortcuts import render 4 | from django.shortcuts import reverse, redirect 5 | from django.http import HttpResponse 6 | 7 | 8 | def cacheSize(request): 9 | return render(request, 'cache/size.html') 10 | 11 | 12 | def cacheAssociativity(request): 13 | return render(request, 'cache/associativity.html') 14 | 15 | 16 | def tlbSize(request): 17 | return render(request, 'tlb/size.html') 18 | 19 | 20 | def miscCores(request): 21 | return render(request, 'misc/cores.html') 22 | 23 | 24 | def miscBits(request): 25 | return render(request, 'misc/bits.html') 26 | 27 | 28 | def miscPagesize(request): 29 | return render(request, 'misc/pagesize.html') 30 | 31 | 32 | def miscPrefetcher(request): 33 | return render(request, 'misc/prefetcher.html') 34 | 35 | 36 | def performanceSingle(request): 37 | return render(request, 'performance/single.html') 38 | 39 | 40 | def performanceMulti(request): 41 | return render(request, 'performance/multi.html') 42 | 43 | 44 | def performanceMemory(request): 45 | return render(request, 'performance/memory.html') 46 | 47 | 48 | def bufferLoad(request): 49 | return render(request, 'buffer/load.html') 50 | 51 | 52 | def bufferStore(request): 53 | return render(request, 'buffer/store.html') 54 | 55 | 56 | def timerPrecision(request): 57 | return render(request, 'misc/timer.html') -------------------------------------------------------------------------------- /web/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.5.2 2 | contourpy==1.0.5 3 | cycler==0.11.0 4 | Django==3.2.15 5 | fonttools==4.37.3 6 | kiwisolver==1.4.4 7 | matplotlib==3.6.0 8 | numpy==1.23.3 9 | packaging==21.3 10 | Pillow==9.2.0 11 | pyparsing==3.0.9 12 | python-dateutil==2.8.2 13 | python-decouple==3.6 14 | python-dotenv==0.21.0 15 | pytz==2022.2.1 16 | six==1.16.0 17 | sqlparse==0.4.3 18 | -------------------------------------------------------------------------------- /web/upload/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/upload/__init__.py -------------------------------------------------------------------------------- /web/upload/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UploadConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'upload' 7 | -------------------------------------------------------------------------------- /web/upload/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cispa/browser-cpu-fingerprinting/1fe8cf6360a758dc434a88321568ca99856f7ba3/web/upload/migrations/__init__.py -------------------------------------------------------------------------------- /web/upload/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | class BenchmarkResult(models.Model): 4 | model = models.CharField(max_length=255) 5 | user_agent = models.CharField(max_length=255) 6 | times = models.JSONField() 7 | benchmark_results = models.JSONField() 8 | b64_charts = models.JSONField() 9 | 10 | def __str__(self): 11 | return self.model -------------------------------------------------------------------------------- /web/upload/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /web/upload/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from django.conf import settings 3 | from django.conf.urls.static import static 4 | 5 | from . import views 6 | 7 | urlpatterns = [ 8 | path('upload/', views.upload, name='upload') 9 | ] --------------------------------------------------------------------------------