icrar / crc32c Goto Github PK
View Code? Open in Web Editor NEWA python package implementing the crc32c algorithm in hardware and software
License: GNU Lesser General Public License v2.1
A python package implementing the crc32c algorithm in hardware and software
License: GNU Lesser General Public License v2.1
First of all thanks for making this package available! I'm making use of this package in aiortc
, a Python implementation of WebRTC, as the SCTP layer uses crc32c checksums. The performance with SSE instructions is amazing, but what's more even the software implementation is faster that crcmod
.
It was recently brought to my attention that attempting to build the package on non-Intel platforms fails, due to the SSE-specific compiler flags (https://github.com/jlaine/aiortc/issues/119), so I've had to add a fallback to crcmod
.
Given that you already have a plain C implementation, how hard would it be to adjust the build system to skip the SSE version altogether on non-Intel platfoms?
From Debian build logs, we can see that tests are failing across all big-endian archs:
e.g. on s390x:
======================================================================
FAIL: test_all (test.test_crc32c.TestLongPhrase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/<<PKGBUILDDIR>>/test/test_crc32c.py", line 113, in test_all
self.assertEqual(self.checksum, crc32c.crc32c(self.val))
AssertionError: 4239873882 != 4025908388
======================================================================
FAIL: test_msvc_examples (test.test_crc32c.TestMisc)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/<<PKGBUILDDIR>>/test/test_crc32c.py", line 96, in test_msvc_examples
assert_msvc_vals(ulonglong_as_bytes(0x88889999EEEE3333), 0x5555AAAA, 0x16F57621)
File "/<<PKGBUILDDIR>>/test/test_crc32c.py", line 92, in assert_msvc_vals
self.assertEqual(expected_crc ^ max32, crc32c.crc32c(b, crc ^ max32))
AssertionError: 3909781982 != 4070212859
======================================================================
FAIL: test_all (test.test_crc32c.TestNumbers1)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/<<PKGBUILDDIR>>/test/test_crc32c.py", line 113, in test_all
self.assertEqual(self.checksum, crc32c.crc32c(self.val))
AssertionError: 3808858755 != 268849953
======================================================================
FAIL: test_all (test.test_crc32c.TestNumbers2)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/<<PKGBUILDDIR>>/test/test_crc32c.py", line 113, in test_all
self.assertEqual(self.checksum, crc32c.crc32c(self.val))
AssertionError: 3219729027 != 1827003070
======================================================================
FAIL: test_all (test.test_crc32c.TestNumbers3)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/<<PKGBUILDDIR>>/test/test_crc32c.py", line 113, in test_all
self.assertEqual(self.checksum, crc32c.crc32c(self.val))
AssertionError: 4091270398 != 2958561646
======================================================================
FAIL: test_all (test.test_crc32c.TestPhrase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/<<PKGBUILDDIR>>/test/test_crc32c.py", line 113, in test_all
self.assertEqual(self.checksum, crc32c.crc32c(self.val))
AssertionError: 576848900 != 1074876099
----------------------------------------------------------------------
Ran 13 tests in 0.001s
FAILED (failures=6)
Test failed: <unittest.runner.TextTestResult run=13 errors=0 failures=6>
Hi, thank you for publishing this package, it's very useful and elegant, and the performance is phenomenal.
It would be great if this package could be distributed on PyPI with pre-compiled wheels, so it can be installed without a build toolchain. Would you be open to configuring the release script to publish such wheels? You could use Travis to build Mac OS and Linux wheels, and Appveyor to build Windows wheels.
I may be able to help out if you would be willing to consider a PR for this.
I'm trying to update package crc32c
to latest(2.2) on ALTLinux. Build is ok on aarch64, i586, ppc64le, x86_64, but fails on armh (armv7-a). For building armh we are using armv8l hardware at 32bit mode. That's why -march=armv8-a+crc+crypto
is wrongly applied.
[00:00:08] + CFLAGS='-pipe -frecord-gcc-switches -Wall -g -O2 -fomit-frame-pointer -march=armv7-a -mthumb'
[00:00:08] + export CFLAGS
[00:00:08] + CXXFLAGS='-pipe -frecord-gcc-switches -Wall -g -O2 -fomit-frame-pointer -march=armv7-a -mthumb'
[00:00:08] + export CXXFLAGS
[00:00:08] + FFLAGS='-pipe -frecord-gcc-switches -Wall -g -O2 -fomit-frame-pointer -march=armv7-a -mthumb'
[00:00:08] + export FFLAGS
[00:00:08] + /usr/bin/python3 setup.py build --debug
[00:00:08] running build
[00:00:08] running build_ext
[00:00:08] platform: armv8l, is_intel: 0, is_arm: 1
[00:00:08] building 'crc32c' extension
[00:00:08] creating build
[00:00:08] creating build/temp.linux-armv8l-3.9
[00:00:08] armh-alt-linux-gnueabi-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -fwrapv -O2 -Wall -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -g -O2 -fomit-frame-pointer -march=armv7-a -mthumb -fPIC -g -DNDEBUG -DIS_ARM -I. -I/usr/include/python3.9 -c _crc32c.c -o build/temp.linux-armv8l-3.9/_crc32c.o -O3 -march=armv8-a+crc+crypto
[00:00:08] _crc32c.c: In function �PyInit_crc32c’:
[00:00:08] _crc32c.c:152:11: warning: implicit declaration of function �_crc32c_arm64_probe’; did you mean �_crc32c_intel_probe’? [-Wimplicit-function-declaration]
[00:00:08] 152 | else if (_crc32c_arm64_probe()) {
[00:00:08] | ^~~~~~~~~~~~~~~~~~~
[00:00:08] | _crc32c_intel_probe
[00:00:08] armh-alt-linux-gnueabi-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -fwrapv -O2 -Wall -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -g -O2 -fomit-frame-pointer -march=armv7-a -mthumb -fPIC -g -DNDEBUG -DIS_ARM -I. -I/usr/include/python3.9 -c checkarm.c -o build/temp.linux-armv8l-3.9/checkarm.o -O3 -march=armv8-a+crc+crypto
[00:00:08] armh-alt-linux-gnueabi-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -fwrapv -O2 -Wall -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -g -O2 -fomit-frame-pointer -march=armv7-a -mthumb -fPIC -g -DNDEBUG -DIS_ARM -I. -I/usr/include/python3.9 -c checksse42.c -o build/temp.linux-armv8l-3.9/checksse42.o -O3 -march=armv8-a+crc+crypto
[00:00:09] armh-alt-linux-gnueabi-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -fwrapv -O2 -Wall -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -g -O2 -fomit-frame-pointer -march=armv7-a -mthumb -fPIC -g -DNDEBUG -DIS_ARM -I. -I/usr/include/python3.9 -c crc32c_adler.c -o build/temp.linux-armv8l-3.9/crc32c_adler.o -O3 -march=armv8-a+crc+crypto
[00:00:09] armh-alt-linux-gnueabi-gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -fwrapv -O2 -Wall -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -fomit-frame-pointer -march=armv7-a -mthumb -pipe -frecord-gcc-switches -Wall -g -O2 -fomit-frame-pointer -march=armv7-a -mthumb -fPIC -g -DNDEBUG -DIS_ARM -I. -I/usr/include/python3.9 -c crc32c_arm64.c -o build/temp.linux-armv8l-3.9/crc32c_arm64.o -O3 -march=armv8-a+crc+crypto
[00:00:09] In file included from crc32c_arm64.c:21:
[00:00:09] crc32c_arm64.c: In function �_crc32c_hw_arm64’:
[00:00:09] /usr/lib/gcc/armh-alt-linux-gnueabi/10/include/arm_neon.h:17035:1: error: inlining failed in call to �always_inline’ �vmull_p64’: target specific option mismatch
[00:00:09] 17035 | vmull_p64 (poly64_t __a, poly64_t __b)
[00:00:09] | ^~~~~~~~~
[00:00:09] crc32c_arm64.c:84:20: note: called from here
[00:00:09] 84 | t0 = (uint64_t)vmull_p64(crc0, k0);
[00:00:09] | ^~~~~~~~~~~~~~~~~~~
[00:00:09] In file included from crc32c_arm64.c:21:
[00:00:09] /usr/lib/gcc/armh-alt-linux-gnueabi/10/include/arm_neon.h:17035:1: error: inlining failed in call to �always_inline’ �vmull_p64’: target specific option mismatch
[00:00:09] 17035 | vmull_p64 (poly64_t __a, poly64_t __b)
[00:00:09] | ^~~~~~~~~
[00:00:09] crc32c_arm64.c:83:20: note: called from here
[00:00:09] 83 | t1 = (uint64_t)vmull_p64(crc1, k1);
[00:00:09] | ^~~~~~~~~~~~~~~~~~~
[00:00:09] In file included from crc32c_arm64.c:21:
[00:00:09] /usr/lib/gcc/armh-alt-linux-gnueabi/10/include/arm_neon.h:17035:1: error: inlining failed in call to �always_inline’ �vmull_p64’: target specific option mismatch
[00:00:09] 17035 | vmull_p64 (poly64_t __a, poly64_t __b)
[00:00:09] | ^~~~~~~~~
[00:00:09] crc32c_arm64.c:82:20: note: called from here
[00:00:09] 82 | t2 = (uint64_t)vmull_p64(crc2, k2);
[00:00:09] | ^~~~~~~~~~~~~~~~~~~
[00:00:09] In file included from crc32c_arm64.c:21:
[00:00:09] /usr/lib/gcc/armh-alt-linux-gnueabi/10/include/arm_neon.h:17035:1: error: inlining failed in call to �always_inline’ �vmull_p64’: target specific option mismatch
[00:00:09] 17035 | vmull_p64 (poly64_t __a, poly64_t __b)
[00:00:09] | ^~~~~~~~~
[00:00:09] crc32c_arm64.c:84:20: note: called from here
[00:00:09] 84 | t0 = (uint64_t)vmull_p64(crc0, k0);
[00:00:09] | ^~~~~~~~~~~~~~~~~~~
[00:00:09] In file included from crc32c_arm64.c:21:
[00:00:09] /usr/lib/gcc/armh-alt-linux-gnueabi/10/include/arm_neon.h:17035:1: error: inlining failed in call to �always_inline’ �vmull_p64’: target specific option mismatch
[00:00:09] 17035 | vmull_p64 (poly64_t __a, poly64_t __b)
[00:00:09] | ^~~~~~~~~
[00:00:09] crc32c_arm64.c:83:20: note: called from here
[00:00:09] 83 | t1 = (uint64_t)vmull_p64(crc1, k1);
[00:00:09] | ^~~~~~~~~~~~~~~~~~~
[00:00:09] In file included from crc32c_arm64.c:21:
[00:00:09] /usr/lib/gcc/armh-alt-linux-gnueabi/10/include/arm_neon.h:17035:1: error: inlining failed in call to �always_inline’ �vmull_p64’: target specific option mismatch
[00:00:09] 17035 | vmull_p64 (poly64_t __a, poly64_t __b)
[00:00:09] | ^~~~~~~~~
[00:00:09] crc32c_arm64.c:82:20: note: called from here
[00:00:09] 82 | t2 = (uint64_t)vmull_p64(crc2, k2);
[00:00:09] | ^~~~~~~~~~~~~~~~~~~
[00:00:09] error: command '/usr/bin/armh-alt-linux-gnueabi-gcc' failed with exit code 1
[00:00:09] error: Bad exit status from /usr/src/tmp/rpm-tmp.32671 (%build)
The following code:
Lines 63 to 65 in 3812a8e
Lines 42 to 43 in 3812a8e
is unconditionally appending -msse4.2 -mpclmul
on all x86 systems. This means that the compiler can optimize any code to use these instructions, and therefore cause the package to crash on a system without it.
To correctly use SSE4.2 runtime detection, you need to append these flags only for files that use them, and make sure that none of the functions declared in them are called before SSE4.2 is successfully detected.
Alternatively, you could mark the functions with something like:
__attribute__((target("sse4.2")))
But I suppose it's less portable.
When I install crc32c-1.2 under win10 x64 system, it comes the following errors. I tried Visual Studio 14 and Visual Studio 2017,but problems still exist. "pip3 install crc32c" can not work either. My python version is 3.6.5
running install
running bdist_egg
running egg_info
writing crc32c.egg-info\PKG-INFO
writing dependency_links to crc32c.egg-info\dependency_links.txt
writing top-level names to crc32c.egg-info\top_level.txt
reading manifest file 'crc32c.egg-info\SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'crc32c.egg-info\SOURCES.txt'
installing library code to build\bdist.win32\egg
running install_lib
running build_ext
building 'crc32c' extension
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\bin\HostX86\x86\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -I. -IC:\Users\guoyi\AppData\Local\Programs\Python\Python36-32\include -IC:\Users\guoyi\AppData\Local\Programs\Python\Python36-32\include "-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\ATLMFC\include" "-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\include" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\include\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\shared" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\winrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\cppwinrt" /Tc_crc32c.c /Fobuild\temp.win32-3.6\Release_crc32c.obj
_crc32c.c
C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\bin\HostX86\x86\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -I. -IC:\Users\guoyi\AppData\Local\Programs\Python\Python36-32\include -IC:\Users\guoyi\AppData\Local\Programs\Python\Python36-32\include "-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\ATLMFC\include" "-IC:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\include" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\include\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\shared" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\winrt" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.17134.0\cppwinrt" /Tccrc32c.c /Fobuild\temp.win32-3.6\Release\crc32c.obj
crc32c.c
crc32c.c(49): error C2065: “asm”: 未声明的标识符
crc32c.c(49): error C2146: 语法错误: 缺少“;”(在标识符“volatile”的前面)
crc32c.c(49): warning C4013: “volatile”未定义;假设外部返回 int
crc32c.c(51): error C2143: 语法错误: 缺少“)”(在“:”的前面)
crc32c.c(71): error C2065: “asm”: 未声明的标识符
crc32c.c(71): error C2146: 语法错误: 缺少“;”(在标识符“volatile”的前面)
crc32c.c(73): error C2143: 语法错误: 缺少“)”(在“:”的前面)
error: command 'C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.14.26428\bin\HostX86\x86\cl.exe' failed with exit status 2
Running with a missing dll on Windows, Python 3.8 leads to
File "lib\site-packages\crc32c\__init__.py", line 29, in <module>
TypeError: category must be a Warning subclass, not 'str'
which breaks the fallback.
This issue is to change the package's import logic. At the moment the package fails to import in platforms where no hardware support is found (i.e., anything other than Intel SSE4.2-capable CPUs) unless an environment variable, specified beforehand, instructs the package to expose its software implementation instead.
This package initially contained only an Intel-based crc32c implementation, but with time a software implementation was incorporated but the importing logic was maintained for backwards compatibility. With the advent of the software implementation (#4) the importing logic has been highlighted as being not necessarily ideal (#5 and #11).
An improved logic, and what most users seem to expect, would work as follow: by default a hardware-based implementation would be offered. If this cannot be offered, the software implementation would be offered instead. This way the package would never fail to import. This would imply that the CRC32C_SW_MODE
variable would become deprecated (we could issue such a deprecation warning upon seeing it). Additionally I would still like it to be clear when a hardware implementation is exposed and when not -- maybe this can be done by attaching an attribute to the crc32c
function, or at the package level. This way people relying on a fast, hardware-based implementation can still check if this is the case and act accordingly.
Since this would be a breaking change (with not too grave consequences though), this would need a bump on the package's major version.
Hi, thank you for this library,
Using an environment variable to unlock the software implementation is not really the idiomatic python style. Would you please consider an alternative that doesn't require to fiddle with os.environ in the import section of the source code.
Maybe a fallback=False
argument or a global module variable or a wrapper function which selects the backend automatically?
Thanks again for this great package. I just wanted to point out that pre-built wheels (which are immensely useful) are missing for Mac OS in the latest released version, 1.7. Hopefully they can be added.
I know that there is a software implementation of this package for non-intel architectures, but that requires an extra environment variable to be declared. ie: "CRC32C_SW_MODE"
But my concern is that, why is it only limited to intel specific instructions set ? What if I want to use this package on ARM machine, and just because the environment variable isn't declared by default it would through me an error "Unsupported platform", even though the platform does support it and has dedicated registers for it.
Or maybe if we can just set the software implementation as the default fallback mechanism, in case we encounter a non-intel arch, we can surely let the user know that we're using software instead of hardware with appropriate logs. There is no point in failing the loading of module, just because its non-intel and the user hasn't declared the environment variable.
Is there any progress done on this front ?? Or maybe you can suggest a workaround ?
On aarch64, ‘pip install crc32c’ builds the wheels from source code and then installs it. It requires the user to have a development environment installed on his system. Also, it takes some time to build the wheels than downloading and extracting the wheels from pypi.
On aarch64, ‘pip install crc32c’ should download the wheels from pypi
@rtobar Please let me know your interest in releasing aarch64 wheels. I can help with this.
File <crc32c_arm64.c> contains this at the top:
// Copyright 2017 The CRC32C Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. See the AUTHORS file for names of contributors.
There is however no file , and file does not contain a BSF-style license.
It seems this file is derived from https://github.com/google/crc32c where those references make sense.
Please make sense of the information - e.g. by adding files <AUTHORS.google_crc32c> and <LICENSE.BSD> (as a snapshot of those upstream files as they were when you forked the code) and updating references to point to those files actually existing within your code project.
I'm looking for an example to calculate the has directly from a file - I'm hoping it's something similar to hashlib where you can stream chunks and update a hasher object. I looked at the testing file, but it looks like there are only tests for byte strings defined directly there. My goal is to be able to validate downloads from Google Storage based on this checksum, since they are provided with the objects. Thanks in advance for your help!
On platforms other than Intel with SSE4.2 (including some virtual machines) there might not be support for hardwarde-based crc32c. However, systems might still require an implementation of the checksum in software. There are pure software implementations of crc32c available and we should look into upgrade the current C code to offer a software alternative if SSE4.2 is not available.
Hi,
Thanks for this great project! I've been having some trouble installing a dependent package with Python 3.10. It's possible this is an Apple Silicon issue. This works fine for py38 and py39. I think what is happening is compiling the wheel dies if I'm installing packages using a Rosetta2 terminal as it gets confused regarding arm vs x86 headers. If I compile in an ARM64 terminal it works.
If a wheel were available, my Rosetta2 terminal would download it and either run it as arm or translate it from x86 to arm.
Thanks so much for reading.
When comparing to other algorithms the result differs. Am I doing anything wrong?
>>> import crc32c
>>> import zlib
>>> zlib.crc32(b'\x01\x02\x03')
1438416925
>>> crc32c.crc32c(b'\x01\x02\x03')
4046516766
Hi, I don't know what happened during the release process but the source tarball on PyPI does not match what is on github, and fails to build:
Running crc32c-1.6/setup.py -q bdist_egg --dist-dir /var/folders/nz/vv4_9tw56nv9k3tkvyszvwg80000gn/T/easy_install-c6x4oqdy/crc32c-1.6/egg-dist-tmp-tbmrrl9s
_crc32c.c:69:15: error: use of undeclared identifier 'crc32c_crc32_sw'; did you mean 'crc32c_crc32'?
{"crc32_sw", crc32c_crc32_sw, METH_VARARGS, "Calculate crc32c using a software implementation."},
^~~~~~~~~~~~~~~
crc32c_crc32
_crc32c.c:40:11: note: 'crc32c_crc32' declared here
PyObject* crc32c_crc32(PyObject *self, PyObject *args) {
See:
https://travis-ci.org/jlaine/aiortc/jobs/480762373
This is the offending diff:
--- github/_crc32c.c 2019-01-17 07:25:02.610620597 +0100
+++ pypi/_crc32c.c 2019-01-17 08:08:56.000000000 +0100
@@ -65,7 +65,8 @@
static PyMethodDef CRC32CMethods[] = {
- {"crc32", crc32c_crc32, METH_VARARGS, "Calculate crc32c using Intel SSE4.2 instruction."},
+ {"crc32", crc32c_crc32, METH_VARARGS, "Calculate crc32c using Intel SSE4.2 instruction."},
+ {"crc32_sw", crc32c_crc32_sw, METH_VARARGS, "Calculate crc32c using a software implementation."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
Could you please bin this release and push out an 1.7 version? (replacing files is not an option, it's going to be on pypi mirrors by now)
These would be nice to have, as python 3.9 is almost out. If getting this to work with travis/appveyor is tough, the new github actions does windows/mac/linux and is pretty slick.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.